使用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 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;
       });
     });  
   } 

,但是这里也有另一个页面的请求调用,例如图像。 我需要每个页面仅发送一个请求。

我该如何解决这个问题?

预先感谢

enter image description here

解决方法

我假设由于transferService.getData()返回了一个Subject(您正在订阅,并且可能没有在任何地方取消订阅组件onDestroy 上的),所以这些订阅仍然有效,并且调用。

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

您将需要保留Subscription时返回的subscribe并在unsubscribe()上致电ngOnDestroy()

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

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

如果您的组件上有多个subscribe(),也许您想利用某种takeUntil之类的自我订阅实现方式

注意:默认情况下,Angular HttpClient订阅是自动退订的,因此在调用unsubscribe()时不需要调用httpClient.get().subscribe()。对于其他所有内容,您都需要致电unsubscribe()

更新:

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

要解决此问题而无需进行重大重构,您必须将其设置为“仅预订一次”或“在调用预订后立即自动取消预订”。这使我们回到了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