ng-idle 订阅无法在另一个订阅中工作

问题描述 投票:0回答:1

我正在使用 @ng-idle/core 包在我的 Angular 2 应用程序中实现空闲超时(当前为 Angular 14)。超过空闲超时后,代码会将用户注销。空闲检测和注销功能已写入我的 app.component.ts 文件中。

当使用空闲时间的硬编码值编写时,代码可以完美运行。但是,我希望可以在后端配置空闲时间。因此,我编写了一个服务类,它在应用程序加载时从后端获取该值。其余代码与硬编码的空闲时间版本完全相同(除了它现在位于我的服务订阅的订阅块内)。但是,ng-idle 订阅永远不会触发。代码如下:

    constructor(
        private router: Router,
        private idle: Idle, cd: ChangeDetectorRef,
        private authSvc: AuthService,
        private sessionDataSvc: SessionDataService,
        private countdownSvc: CountdownService
      ) {

    // set idle parameters
    this.sessionDataSvc.getSessionProperties().subscribe(( {data} ) => {
      let session_timeout = data.sessionProperties.session_idle_timeout
      // set the idle and timeout values
      // let session_timeout = 30;
      idle.setIdle(session_timeout) // how long can they be inactive before considered idle, in seconds
      idle.setTimeout(this.TIMEOUT); // how long can they be idle before considered timed out, in seconds
      idle.setInterrupts(DEFAULT_INTERRUPTSOURCES); // provide sources that will "interrupt" aka provide events indicating the user is active

      console.log("Setting idle timeout to " + session_timeout + " seconds")
       
      // Some code snipped for brevity

      // do something when the user has timed out
      idle.onTimeout.subscribe(() => {
        console.log("onTimeout called")
        this.idleState = "TIMED_OUT"
        this.authSvc.logout()
        this.reset()
        this.router.navigate(['login'], { queryParams: { reason: "Session Timeout. Please re-login" } });
      });
      // do something as the timeout countdown does its thing
      });
  

        console.log("Done with setting idle timeout")
        });
      }
    
    reset() 
    {
        // we'll call this method when we want to start/reset the idle process
        // reset any component state and be sure to call idle.watch()
        this.idle.watch();
        this.idleState = "NOT_IDLE";
        this.countdown = null;
        this.lastPing = null;
    }

注意,ng-idle 包有 4 个订阅方法 - onIdleStart、onIdleEnd、onTimeoutWarning 和 onTimeout。我故意从上面的代码中省略了前三个,以便在我的写作中简短 - 否则它们存在于代码中。 this.sessionDataSvc.getSessionProperties() 正在工作,因为 console.log 消息显示日志消息

Setting idle timeout to 30 seconds

显示在控制台日志中(与上面代码中的其他日志消息

"Done with setting idle timeout"
一样)。但没有任何 ng-idle 订阅被触发。

正如我上面提到的,如果我要注释掉这些行

this.sessionDataSvc.getSessionProperties().subscribe(( {data} ) => {
  let session_timeout = data.sessionProperties.session_idle_timeout

并启用线路:

// let session_timeout = 30;

相反(这是硬编码的情况),@ng-idle 订阅按设计和记录工作。那么为什么它们不在服务订阅内?

angular typescript rxjs ng2-idle
1个回答
0
投票

subscribe
转换为另一个中的
observable
是一种不好的做法,称为“回调地狱”,为此,您需要使用
observables
中的高阶运算符(例如
RxJs
)来处理
switchMap
concatMap
mergeMap
exhaustMap
取决于您想要实现的目标。

如果你不熟悉这些操作符,你可以阅读我不久前给出的this简短解释,或者阅读官方docs

鉴于您的代码示例,您可以像下面这样适当地重构您的逻辑,在本例中,我使用

switchMap
,但是,这又取决于需求:

...
someFunction(): void {
 this.sessionDataSvc.getSessionProperties().pipe(
   switchMap(({ data }) => {
     // it should be const rather than let, you are not modifying its value
     const sessionTimeout = data.sessionProperties.session_idle_timeout;
  
     idle.setIdle(sessionTimeout);
     idle.setTimeout(this.TIMEOUT);
     idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
     return idle.onTimeout; // returns an Observable
   })
 )
 .subscribe(() => {
   this.idleState = "TIMED_OUT"
   this.authSvc.logout()
   this.reset()
   this.router.navigate(['login'], { queryParams: { reason: "Session Timeout. Please re-login" } });
 });
}

reset(): void {
 this.idle.watch();
 this.idleState = "NOT_IDLE";
 this.countdown = null;
 this.lastPing = null;
}
© www.soinside.com 2019 - 2024. All rights reserved.