Angular 使用服务的多个可观察请求

Angular Multiple Observable Requests with using Service

Demo 在我的应用程序中,我使用服务在

之间进行通信
import {Injectable} from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { TransferModel } from '../models/transfer';

@Injectable()
export class TransferService{
    constructor(){}
    private paramSource = new BehaviorSubject(new TransferModel());
    getData = this.paramSource.asObservable();
    setData(param:TransferModel) { this.paramSource.next(param)} 
}

我的问题是,当我转到组件时,它运行良好,但在页面中也发送其他页面请求。我的意思是例如我在 Courses.component

 constructor(private transferService:TransferService,private dataService:DataService,sessionService:SessionService,private router:Router) { 
    this.transferService.getData.subscribe(x=>{
      this.transfer=x; if(!this.transfer.ExamId || this.transfer.ExamId<=0){ this.router.navigateByUrl("/home");return;}
      this.dataService.Post(URLS.url.coursePage.getCourses,{Id:this.transfer.ExamId}).subscribe(elem=>{
        this.courses=elem;
      });
    });  
 }

上面的代码在我单击一门课程时获取课程列表,下面的函数 运行 和

 goToSubject(id){
    this.transfer.CourseId=id;
    this.transferService.setData(this.transfer);
    this.router.navigateByUrl("/subjects");
  }

转到科目部分。在主题组件中,我使用构造函数发送请求。

 constructor(private transferService:TransferService,private dataService:DataService,sessionService:SessionService,private router:Router) { 
     this.transferService.getData.subscribe(x=>{
       this.transfer=x; if(!this.transfer.ExamId || this.transfer.ExamId<=0){ this.router.navigateByUrl("/home"); }
       this.dataService.Post(URLS.url.subjectPage.getSubjects,{ExamId:this.transfer.ExamId,CourseId:this.transfer.CourseId}).subscribe(elem=>{
         this.subjects=elem;
       });
     });  
   } 

但这里还有另一个页面的请求调用,例如图片中的。 我需要每个页面只发送一个请求。

我该如何解决这个问题?

提前致谢

我假设因为 transferService.getData() returns 一个 Subject,你正在订阅,并且可能不会取消订阅 组件 onDestroy 在任何地方,这些订阅仍然有效并被调用。

您的 goToSubject() 调用 this.transferService.setData(this.transfer);,它基本上会调用所有订阅。

您需要保留 subscribe 时返回的 Subscription 并在 ngOnDestroy()

上调用 unsubscribe()
subscription: Subscription;
constructor(...){
    this.subscription = this.transferService.getData.subscribe(x=>{
        ...
    });
}

ngOnDestroy() {
    if(this.subscription) {
        this.subscription.unsubscribe();
        this.subscription = null;
    }
}

如果您的组件上有多个 subscribe(),也许您想利用某种 self-subscribing-implementation,例如 takeUntil

注意:AngularHttpClient订阅默认是self-unsubscribing,所以调用httpClient.get().subscribe()时不需要调用unsubscribe()。对于其他一切,您需要调用 unsubscribe().

更新:

查看您提供的 stackblitz 演示后,确认问题出在 transferService.getData() 主题上。然而,即使 ngOnDestroy() 取消订阅它仍然在调用,因为你在重定向之前有 this.transferService.setData(..),这基本上调用了 transferService.getData().subscribe(...).

要在不进行重大重构的情况下解决这个问题,您必须将其设为 'Subscribe only once' 或 'automatically unsubscribe as soon as it subscribe is called'。这让我们回到 takeUntil.

courses.component 和 subjects.component

constructor() {
    const subj: Subject<boolean> = new Subject<boolean>();
    this.transferService.getData
        .pipe(takeUntil(subj))
        .subscribe((result) => {
            subj.next(true);
        });
 }

更新 2:

Stackblitz demo link