在计时器内重置订阅

时间:2019-12-05 15:30:13

标签: angular rxjs rxjs6

场景:

我有一个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();
          }
        });
    });
  }

1 个答案:

答案 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()