繁体   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