Как остановить интервал в Angular 7? - PullRequest
1 голос
/ 30 марта 2019

У меня есть функция, которая генерирует значения непрерывно.

Что я хочу ??

Если условие 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 ]

2 голосов
/ 30 марта 2019

Имхо, 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>

Надеюсь, это поможет

1 голос
/ 30 марта 2019

Я думаю, что лучше всего использовать takeUntil трубу.Посмотрите на этот пример .

Я переписал ваш код, используя takeUntil и filter pipe.И я переместил функцию 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);
    }
  );
}
1 голос
/ 30 марта 2019

Вы пытались отписаться в ngOnDestroy методе?

0 голосов
/ 30 марта 2019

На самом деле, похоже, что вам нужно установить таймер на определенную продолжительность, попробуйте

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$ в шаблоне.

Надеюсь, это поможет

0 голосов
/ 30 марта 2019

Насколько я знаю, функция interval перестает излучать после отказа от подписки, я также создал пример stackblitz , чтобы продемонстрировать это.

По какой-то причине ваш код не 't вызов метода unsubscribe, и я бы посоветовал вам поискать здесь проблему, возможно, добавив отладчик перед вызовом unsubscribe, чтобы проверить, действительно ли он выполняется.

Также проверьте, что вы звоните unsubscribe на правильном объекте, например, это должна быть подписка , а не timer $ .

Но я думаю, что нет никаких сомнений в том, что проблема в коде, который вы показали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...