首页 > 解决方案 > 在计时器内重置订阅

问题描述

设想:

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

标签: angularrxjsrxjs6

解决方案


这就是为什么嵌套订阅是一种反模式并且应该避免使用的部分原因......您希望使用正确的运算符来为您处理订阅和取消订阅:

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

推荐阅读