typescript 主题完成后rxjs计时器仍在运行()

q7solyqu  于 2023-02-25  发布在  TypeScript
关注(0)|答案(1)|浏览(129)

我有下面的代码来实现我的Angular 8项目中的两件事。

  1. api每30秒调用一次,我正在使用rxjs计时器来跟踪。
    1.每当我通过websocket接收数据时,我都想调用相同的api并将计时器重置为30秒。
    问题:当我离开页面时,计时器似乎仍在运行,因为我仍然可以看到网络中的API调用。我不确定此链接是否指向takeUntil泄漏,请帮助!
import {Observable, Subject, timer} from 'rxjs';
import {finalize, takeUntil, takeWhile, tap} from 'rxjs/operators';

countdown = 30;
receivedWS = false;
private _unsubscribeAll: Subject<any> = new Subject();

ngOnInit() {
    this._networkService.getEventListener().pipe(takeUntil(this._unsubscribeAll)).subscribe((res) =>          {
      if (res) {
        this.receivedWS = true;
        this.myService.getUsers().then(() => this.receivedWS = false);
      }
    });

    this._timer();
}

 private _timer(): void {
    timer(1000, 1000).pipe(
      finalize(() => {
        this.countdown = 30;
        this.myService.getUsers(); //api call
        this._timer();
      }),
      takeWhile(() => this.countdown > 0 && this.receivedWS = false),
      takeUntil(this._unsubscribeAll),
      tap(() => this.countdown--)
    ).subscribe();
 }

ngOnDestroy(): void {
    this._unsubscribeAll.next(true);
    this._unsubscribeAll.complete();
}

我尝试过的:我尝试显式取消订阅主题,但却得到了一个错误UnsubscriptionErrorImpl。

ngOnDestroy(): void {
    this._unsubscribeAll.next(true);
    this._unsubscribeAll.complete();
    this._unsubscribeAll.unsubscribe();
  }

UnsubscriptionErrorImpl

jgovgodb

jgovgodb1#

    • 为什么您的代码不能按预期工作?**

当用户离开页面时,OnDestroy被调用,this._unsubscribeAll.next(true)被调用。这触发了_timer()方法中的finalize()运算符。在finalize子句的末尾,您调用this._timer(),这意味着您重新订阅了您的计时器,它将重新开始发送值(无限期)。

    • 如何实现您的愿望**

我建议你以不同的方式构建你的代码。

    • 一个

或者看看我下面的代码和其中的注解:

timerIntervalInMillis = 30_000;

stopTimerSubject = new Subject<void>();
restartTimerSubject = new Subject<void>();

unsubscribeAllSubject = new Subject<void>();

/* - timer$ makes an emission every xy milliseconds, yet its pipe...
   - ...unsubscribes when stopTimerSubject is triggered
   - ...resubscribes when restartTimerSubject is triggered
   - ...unsubscribes for good when unsubscribeAllSubject is triggered */

timer$ = timer(this.timerIntervalInMillis, this.timerIntervalInMillis).pipe(
  takeUntil(this.stopTimerSubject),
  repeat({ delay: () => this.restartTimerSubject }),
  takeUntil(this.unsubscribeAllSubject)
);

ngOnInit(): void {
  // The pipe below takes care of the incoming websocket data:
  const webSocketObs$ = this._networkService.getEventListener().pipe(
    filter((data) => !!data),
    tap((data) => console.log('Data from Websocket:', data)),
    takeUntil(this.unsubscribeAllSubject)
  );

  // The pipe below gets triggered if
  // - data from websocket comes in
  // - or if a timer-tick occured
  merge(webSocketObs$, this.timer$)
    .pipe(
      // Stop the timer before the API-request is made:
      tap(() => this.stopTimerSubject.next()),
      switchMap(() =>
        this.myService.getUsers().pipe(
          takeUntil(this.unsubscribeAllSubject),
          tap((data) => {
            console.log('Fetched Users:', data);
            // On request completion: Restart of the reset timer:
            this.restartTimerSubject.next();
          })
        )
      ),
      takeUntil(this.unsubscribeAllSubject)
    )
    .subscribe();
}

ngOnDestroy(): void {
  this.unsubscribeAllSubject.next();
}

相关问题