场景:
我有一个api调用(this.service.checkStatus(this.movieForm.value.movie)
),应该每60秒使用一次。在60秒之间,我需要显示1秒计数器(类似x seconds until next call
)。因此,我使用了两个计时器(source$
和source2$
)。但是以下代码的问题是source2$
不会在新的api调用后停止,而是每60秒创建一个新的订阅。旧的source2$
订阅仍将增加1,而新的订阅将从0开始并造成混乱。我该如何解决?
下面是我的代码。
代码:
source$ = timer(0, 60000); // every 60 seconds it will emit
source2$ = timer(0, 1000); // every 1 second it will emit
...
getStatus() {
this.apiSubscription$ = this.source$.subscribe(() => {
// I need to reset this timersubscription. so that the val always starts from 0
this.timerSubscription$ = this.source2$.subscribe((val: number) => {
this.timer = 60 - val;
this.progress.nativeElement.style.width = (val / 60) * 100 + '%';
});
this.service.checkStatus(this.movieForm.value.movie)
.pipe(take(1))
.subscribe(res => {
const response: any = res;
if (!response.status) {
// do stuff 1
} else {
// do stuff 2
this.apiSubscription$.unsubscribe();
}
});
});
}
答案 0 :(得分:1)
这就是为什么嵌套订阅是一种反模式的原因,应该避免...您想使用适当的运算符来为您处理订阅和取消订阅:
this.apiSubscription$ = source1$.pipe(
switchMap(() => { // switchMap subscribes to new inner subscriptions and cancels previous ones
const counter$ = source2$.pipe(
tap(timer => { // tap lets you produce side effects
this.timer = 60 - timer;
this.progress.nativeElement.style.width = (timer / 60) * 100 + '%';
})
)
const status$ = this.service.checkStatus(this.movieForm.value.movie).pipe(
first(), // first is more semantic IMO
tap(response => {
if (!response.status) {
// do stuff 1
} else {
// do stuff 2
}
})
)
return combineLatest(counter$, status$); // combine observables
}),
// takeWhile will end your subscription for you if the condition is false
takeWhile(([timer, statusResponse]) => !!statusResponse.status)
).subscribe()