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:
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: