Angular 如何控制rxjs中的间隔在角模式下禁用计时器
我尝试在angular应用程序中实现一种“会话计时器”。当用户在指定时间段内未单击任何键时,它将注销用户。一切正常,直到第一次注销。第二次登录后,计时器的重置方法不起作用。无论执行何种操作,用户都会在指定时间后注销 我在上做了一个演示 以下是服务代码:Angular 如何控制rxjs中的间隔在角模式下禁用计时器,angular,rxjs,Angular,Rxjs,我尝试在angular应用程序中实现一种“会话计时器”。当用户在指定时间段内未单击任何键时,它将注销用户。一切正常,直到第一次注销。第二次登录后,计时器的重置方法不起作用。无论执行何种操作,用户都会在指定时间后注销 我在上做了一个演示 以下是服务代码: @Injectable({ providedIn: "root" }) export class SessionTimerService { private readonly sessionTimer: Observable<num
@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();
}
}
}
@可注入({
提供于:“根”
})
导出类SessionTimerService{
私有只读会话计时器:可观察=间隔(10000);//10秒
私有sessiontimecontroller:主题;
公共构造函数(专用只读路由器:路由器){}
public initTimer():void{
this.sessionTimerController=新主题();
这是sessionTimer
.烟斗(
以(1)为例,
takeUntil(此.sessionTimerController)
)
.订阅(()=>{
控制台日志(“注销”);
this.sessiontimecontroller.next();
this.sessiontimecontroller.complete();
this.router.navigate([“/login”]);
});
}
公共重置计时器():void{
if(this.sessiontimecontroller&!this.sessiontimecontroller.closed){
控制台日志(“重置”);
this.sessiontimecontroller.next();
this.sessiontimecontroller.complete();
this.initTimer();
}
}
公共停止计时器():void{
if(this.sessiontimecontroller&!this.sessiontimecontroller.closed){
控制台日志(“停止”);
this.sessiontimecontroller.next();
this.sessiontimecontroller.complete();
}
}
}
window.relad()
不是这个问题的好答案。问题是,在第二次登录时,您正在创建两个独立的计时器,因为第一次登录时是this.sessionTimerController===null
,并且您检查了以下条件:
onMouseMove
main组件的构造函数中
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>();
...
private sessionTimerController:Subject=newsubject();
...
public initTimer():void{
log('initTimer');
this.sessiontimecontroller.next();
this.sessiontimecontroller.complete();
this.sessionTimerController=新主题();
...
现场演示:
在我看来,在您的用例中,完全摆脱
主题将更容易,因为这只会使事情变得复杂,并使用单个订阅对象来取消任何以前的计时器。问题是,您在第二次登录时创建了两个独立的计时器,因为在第一次登录时是this.sessionTimerController===null
,您可以检查以下条件:
内部onMouseMove
在main组件的构造函数中
第二个问题是方法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>();
...
private sessionTimerController:Subject=newsubject();
...
public initTimer():void{
log('initTimer');
this.sessiontimecontroller.next();
this.sessiontimecontroller.complete();
this.sessionTimerController=新主题();
...
现场演示:
在我看来,在您的用例中,完全摆脱主题将更容易,因为这只会使事情变得复杂,并使用单个订阅对象来取消任何以前的计时器。RXJS功能强大,您可以取消订阅正在进行的事件,因此我在这个解决方案中设法做到这一点n
这是服务代码
@注射的({
提供于:“根”
})
导出类SessionTimerService{
savedSub:订阅;
公共构造函数(专用只读路由器:路由器){
}
public initTimer():void{
this.savedSub=of(true).pipe(延迟(5000))
.订阅(()=>{
this.router.navigate(['login']);
this.savedSub.unsubscribe();
})
}
公共重置计时器():void{
if(this.savedSub){
this.savedSub.unsubscribe();
this.savedSub=null;
this.initTimer();
}
}
onDestroy(){
if(this.savedSub){
this.savedSub.unsubscribe();
this.savedSub=null;
}
}
}
initTimer将等待5秒。当没有任何东西可以阻止它时,它将注销
当您拥有的订阅引用取消订阅时
将消失,并且不会触发。。
单击鼠标,我们将取消订阅
并从开始重新运行计时器
但是如果无人停止计时器,您需要取消订阅或null
订阅的值..这就是为什么我们在ngondestory
工作时从主组件调用onDestroy
ngondestory(){
this.sessionTimer.onDestroy();
}
希望这能解决您的问题。RXJS功能强大,您可以取消订阅正在进行的活动,所以我在这个解决方案中做到了这一点
这是服务代码
@注射的({
提供于:“根”
})
导出类SessionTimerService{
savedSub:订阅;
公共构造函数(专用只读路由器:路由器){
}
public initTimer():void{
this.savedSub=of(true).pipe(延迟(5000))
.订阅(()=>{
this.router.navigate(['login']);
this.savedSub.unsubscribe();
})
}
公共重置计时器():void{
if(this.savedSub){
this.savedSub.unsubscribe();
this.savedSub=null;
this.initTimer();
}
}
onDestroy(){
if(this.savedSub){
this.savedSub.unsubscribe();
this.savedSub=null;
}
}
}
initTimer将等待5秒。当没有任何东西可以阻止它时,它将注销
当订阅