簡體   English   中英

如何控制rxjs中的間隔? - 以角度停用計時器

[英]How to control interval in rxjs? - inactivate timer in angular

我嘗試在 angular 應用程序中實現一種“會話計時器”。 當(她)在指定時間內沒有點擊任何鍵時,它將注銷用戶。 一切正常,直到第一次注銷。 第二次登錄后,定時器的重置方法不起作用。 無論執行的操作如何,用戶都會在指定時間后注銷。

我在StackBlitz上做了一個演示

這是服務代碼:

@Injectable({
  providedIn: "root"
})
export class SessionTimerService {
  private readonly sessionTimer: Observable<number> = interval(10000); // 10 sec
  private sessionTimerController: Subject<void>;

  public constructor(private readonly router: Router) {}

  public initTimer(): void {
    this.sessionTimerController = new Subject<void>();
    this.sessionTimer
      .pipe(
        take(1),
        takeUntil(this.sessionTimerController)
      )
      .subscribe(() => {
        console.log("logout");
        this.sessionTimerController.next();
        this.sessionTimerController.complete();
        this.router.navigate(["/login"]);
      });
  }

  public resetTimer(): void {
    if (this.sessionTimerController && !this.sessionTimerController.closed) {
      console.log("reset");
      this.sessionTimerController.next();
      this.sessionTimerController.complete();

      this.initTimer();
    }
  }

  public stopTimer(): void {
    if (this.sessionTimerController && !this.sessionTimerController.closed) {
      console.log("stop");
      this.sessionTimerController.next();
      this.sessionTimerController.complete();
    }
  }
}

window.relaod()不是這個問題的好答案。

問題是您在第二次登錄時創建了兩個獨立的計時器,因為第一次登錄時this.sessionTimerController === null並且您檢查此條件:

  1. onMouseMove里面。
  2. MainComponent的構造函數中。

第二個問題是方法initTimer()不檢查是否已經有一個計時器:

因此,在創建新計時器之前,您可以完成前一個計時器,這樣您就知道永遠只有一個計時器:

private sessionTimerController: Subject<void> = new Subject<void>();

...

public initTimer(): void {
  console.log('initTimer');

  this.sessionTimerController.next();
  this.sessionTimerController.complete();
  this.sessionTimerController = new Subject<void>();
  ...

現場演示: https : //stackblitz.com/edit/angular-session-timer-yqdxco?file= src/app/ session-timer.service.ts

在我看來,在您的用例中,完全擺脫Subject會更容易,因為它只會使事情變得復雜並使用單個Subscription對象來取消任何以前的計時器。

RXJS 功能強大,您可以unsubscribe正在進行的事件,因此我設法在此解決方案中做到了這一點

https://stackblitz.com/edit/angular-session-timer-jpkxnj

這是服務代碼


@Injectable({
  providedIn: "root"
})
export class SessionTimerService {

  savedSub: Subscription;

  public constructor(private readonly router: Router) {

  }

  public initTimer(): void {

    this.savedSub = of(true).pipe(delay(5000))
    .subscribe(() => {
      this.router.navigate(['login']);
      this.savedSub.unsubscribe();
    })

  }

  public resetTimer(): void {
    if(this.savedSub){
    this.savedSub.unsubscribe();
    this.savedSub = null;
    this.initTimer();
    }
  }

  onDestroy(){
    if(this.savedSub){
    this.savedSub.unsubscribe();
    this.savedSub = null;
    }
  }


}

initTimer 將等待 5 秒。當沒有任何事情可以阻止它時,它會在您unsubscriped的訂閱引用消失並且不會觸發時注銷。單擊鼠標,我們將unsubscribe並從頭開始重新運行計時器。

但你需要取消或null訂閱的值,如果沒有人停止計時器..那為什么我們做的onDestroy從主組件調用時ngOnDestroy工作

  ngOnDestroy(){
    this.sessionTimer.onDestroy();
  }

希望能解決你的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM