[英]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
並且您檢查此條件:
onMouseMove
里面。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.