在计时器内重置订阅
Reset subscription inside a timer
场景:
我有一个 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();
}
});
});
}
这就是为什么嵌套订阅是一种反模式并且应该避免的部分原因...您想使用适当的运算符来为您处理订阅和取消订阅:
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()
场景:
我有一个 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();
}
});
});
}
这就是为什么嵌套订阅是一种反模式并且应该避免的部分原因...您想使用适当的运算符来为您处理订阅和取消订阅:
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()