如何在Angular 7中停止间隔?

时间:2019-03-30 14:40:35

标签: angular rxjs

我有一个连续发出值的函数。

我想要什么?

如果满足Math.sign条件,我将用户重定向到另一个屏幕并显示一条敬酒消息。

但是现在,由于间隔是连续的,所以连续显示吐司消息。

我尝试了什么?

this.subscription.unsubscribe()处于if(Math.sign)条件下,但无效。

任何建议如何在以下代码中停止间隔?

startTimer(validUntil: string) {
    this.counter$ = interval(1000).pipe(
        map((x) => {
            this.diff = Math.floor((new Date(validUntil).getTime() - new Date().getTime()) / 1000);

            if (Math.sign(this.diff) == -1) {
                //Tried this.subscription.unsubscribe() here

                // Redirects me to another component
                this.goBack(true);
            }
            return x;
        }));

    this.subscription = this.counter$
        .subscribe((x) => {
            this.message$ = this.dhms(this.diff);
        });
}


goBack(requestExpired: boolean) {
    if (requestExpired == true) {
        this.messageDialogService.presentToast('Expired')
    }
    this.router.navigate(['mypage']);
}

5 个答案:

答案 0 :(得分:1)

您是否尝试过用"?"方法退订?

答案 1 :(得分:1)

Imho,takeWhile里面有条件是最明显的方法。

例如:

startTimer(validUntil) {
  this.counter$ = interval(1000).pipe(

    // turn value emissions into diffs
    map(() => Math.floor((new Date(validUntil).getTime() - new Date().getTime()) / 1000)),

    // this is needed to terminate when condition is met
    takeWhile(diff => Math.sign(diff) !== -1),

    // when terminated on conditions -- navigate back
    finalize(()=>{
      this.goBack(true);
    })

    // just in case if user navigates out before condition is met
    takeUntil(this.destroy$)
  )
  .subscribe(diff => {
    this.message$ = this.dhms(diff);
  });
}

注意:但是,我怀疑您根本不需要counter$。您只能将message$流与异步管道一起使用,例如

控制器

startTimer(validUntil) {
  this.messages$ = interval(1000).pipe(
    // ...
  )
}

模板

<div>{ messages$ | async }</div>

希望这会有所帮助

答案 2 :(得分:1)

我认为最好的方法是使用takeUntil管道。 看this example

我使用takeUntilfilter管道重写了您的代码。然后,我将goBack函数移到了订阅函数的complete回调中。

startTimer(validUntil: string) {
  this.counter$ = interval(1000);
  const takeUntil$ = this.counter$.pipe(
    filter(x => {
      this.diff = Math.floor((new Date(validUntil).getTime() - Date.now()) / 1000);
      return Math.sign(this.diff) === -1;
    })
  );
  this.counter$.pipe(takeUntil(takeUntil$)).subscribe(
    x => {
      this.message$ = this.dhms(this.diff);
    },
    undefined,
    () => {
      this.goBack(true);
    }
  );
}

答案 3 :(得分:0)

据我所知,interval函数在退订后停止发出,我还创建了一个stackblitz example进行演示。

由于某种原因,您的代码未调用unsubscribe方法,建议您在此处查找问题,也许在调用unsubscribe之前先添加调试器,以检查其是否确实存在被执行。

还要检查您是否在正确的对象上调用unsubscribe,例如,它必须是 subscription ,而不是 timer $

但是我认为毫无疑问,问题出在您显示的代码中。

答案 4 :(得分:0)

实际上,您似乎需要为给定持续时间设置计时器,请尝试

timer(0, 1000).pipe(
  take(N)
)

其中N是当前时间与validUntil之间的秒数差。所以

startTimer(validUntil) {
   // duration in seconds till invalid
  const duration = Math.floor((new Date(validUntil).getTime() - Date.now()) / 1000));

  this.messages$ = timer(0, 1000).pipe(
    // we take 1 more emission to encompass starting emission
    take(duration + 1)

    // once given number of seconds passed -- navigate back
    finalize(()=>{
      this.goBack(true);
    })

    // just in case if user navigates out before condition is met
    // this is needed if you wont use |async pipe
    takeUntil(this.destroy$)

    // map to display time
    map(value => this.dhms(duration - value))
  );
}

然后将| async管道应用于模板中的message$

希望这会有所帮助

相关问题