简体   繁体   中英

interval rxjs not clearing timer

I have an Input property as setter:

   @Input() set moduleData(value: any) {
    this._moduleData = value;
    this.destroy$.next();
    this.destroy$.complete();
    this.startAttempt();
  } 



  startAttempt() {
    if (!this.isExamStarted()) {
      console.log("exam is not started");
      interval(1000).pipe(takeUntil(this.destroy$)).subscribe((res) => {
        if (
          this.canStartAssessment(this.moduleData.module_progress.start_time)
        ) {
          console.log("exam can be started now");
          this.getTimeRemainingInExam();
        } else {
          this.getTimer(
            this.moduleData.module_progress.start_time,
            false
          );
        }
      });
    } else {
      this.getTimeRemainingInExam();
    }
  }


ngOnDestroy(): void {
    console.log("componenet destroyef");
    this.destroy$.next();
    this.destroy$.complete();
  }

By using the takeUntil operator , im trying to stop the timer. I can see that the timer still runs even after the component is destroyed. Also when the input property changes i can see that in 1 sec it is getting called twice . For ex , the logs are printed twice , as many as the input of previous values. How to clear all the intervals when the input property changes before starting interval again?

You don't have to complete the multicast observable destroy$ .

  1. Once complete, they aren't started again.
  2. If the observable is used only for the takeUntil , the complete is redundant. Just the next is enough. Refer here .

Try the following

@Input() set moduleData(value: any) {
  this._moduleData = value;
  this.destroy$.next(); // <-- `complete()` not required
  this.startAttempt();
}

...
ngOnDestroy(): void {
  console.log("component destroyed");
  this.destroy$.next(); // <-- `complete()` not required
}

The .subscription has to be killed. You could add this snippet

interval(1000).pipe(takeUntil(this.destroy$)).subscribe((res) => {
  [...]
});

into a subscriptions array and unsubscribe from it in the ngOnDestroy lifecycle hook.

subscriptions: Subscription[] = [];

startAttempt() {
  [...]
  this.subscriptions.push(
    interval(1000).pipe(takeUntil(this.destroy$)).subscribe((res) => {
      [...]
    })
  )
  [...]
}

ngOnDestroy() {
  this.subscriptions.forEach(subscription => subscription.unsubscribe());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM