首页 > 解决方案 > 使用服务的角度多个可观察请求

问题描述

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

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

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

我怎么解决这个问题?

提前致谢 在此处输入图像描述

标签: angularobservablesubscribe

解决方案


我假设由于transferService.getData()返回 a Subject,您正在订阅它,并且可能不会在任何地方取消订阅组件onDestroy,这些订阅仍然有效并被调用。

您的goToSubject()电话this.transferService.setData(this.transfer);基本上调用了所有订阅。

当你打电话时,你需要等待Subscription被退回subscribeunsubscribe()ngOnDestroy()

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

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

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

unsubscribe()注意:Angular HttpClient 订阅默认是自行取消订阅的,所以调用时不需要调用httpClient.get().subscribe(). 对于其他一切,您需要调用unsubscribe().

更新:

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

要在不进行重大重构的情况下解决此问题,您必须将其设为“仅订阅一次”或“调用订阅后立即自动取消订阅”。这让我们回到takeUntil.

在 course.component 和 subject.component 中

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

更新 2:

Stackblitz 演示链接


推荐阅读