实现Ionic / Angular的会话超时服务,每次新用户交互时都会重置计时器

时间:2017-08-22 11:11:56

标签: angular typescript rxjs ionic3

我试图调整我为会话超时创建的一些代码。 每当用户与该功能交互时,我想重置计时器以再次开始倒计时。我在解决如何向此example

注入类似代码时遇到了困难

C#代码 - 我试图整合:

var update = new Subject<bool>();
var res =
    update
        .Select(x => Observable.Interval(TimeSpan.FromSeconds(10.0)))
        .Switch();
res
    .Subscribe(_ => Console.WriteLine("Status sent."));
update.OnNext(true);
res
    .Subscribe(_ =>
    {
        update.OnNext(true);
        Console.WriteLine("Status sent.");
    });

据我所知,RxJS库的C#风格和我的变量名映射的Typescript RxJS等价物是:

C#/example Typescript/mine
update resetManager
.Select .map(来自here - (参见标题标题))
.OnNext .next
.Interval .timer

我以为我可以插入一个do并链接resetManager - 但由于一个是布尔值而另一个是AuthState,我似乎遇到了困难。

我想知道RxJS大师是否可以提供建议。欢呼声。

import { Injectable }           from '@angular/core';
import { Observable }           from 'rxjs/Observable';
import { BehaviorSubject }      from 'rxjs/BehaviorSubject';
import                               'rxjs/add/operator/map';
import                               'rxjs/add/operator/filter';
import                               'rxjs/add/Observable/timer';
import                               'rxjs/add/operator/do';
import                               'rxjs/add/operator/switch';
@Injectable()
export class AuthService {
  private authState:    AuthState;
  private authManager:  BehaviorSubject<AuthState>;
  public  authChange$:  Observable<AuthState>;
  private resetManager: Subject<boolean>;
  constructor() {
    this.authManager = new BehaviorSubject(AuthState.LOGGED_OUT);
    this.authChange$ = this.authManager.asObservable();
    this.authChange$
      .filter((authState:AuthState) => authState === AuthState.LOGGED_IN)
      .map(   (authState:AuthState) => Observable.timer(SESSION_TIMEOUT))
      .do(    () => 
        console.log('Logged In. Session Timout counting down from now'))
      .switch()
      .subscribe( () => {console.log('Timer ended: Logging out')
                         this.logout();
                        });
  }

  login() {
    this.setAuthState(AuthState.LOGGED_IN);
  }
  logout() {
    this.setAuthState(AuthState.LOGGED_OUT);
  }

  resetSessionTimer() {
    this.resetManager.next(true);
  } 

  emitAuthState():void {
    this.authManager.next(this.authState);
  }

  private setAuthState(newAuthState:AuthState):void {
    console.log('AuthService: setAuthState: ', 
        AuthState[newAuthState.toString()]);
    if (newAuthState != this.authState) {
      this.authState = newAuthState;
      this.emitAuthState();
    }
  }

export enum AuthState {
  LOGGED_IN,
  LOGGED_OUT
}

const SESSION_TIMEOUT = 5000;

1 个答案:

答案 0 :(得分:0)

我终于知道如何做到这一点......

import { Events }               from 'ionic-angular';
import { Observable }           from 'rxjs/Observable';
import { Subscription }         from 'rxjs/Subscription';
import                               'rxjs/add/observable/interval';
import                               'rxjs/add/operator/mapTo';
import                               'rxjs/add/observable/defer';
import                               'rxjs/add/observable/of';
import                               'rxjs/add/operator/merge';
import                               'rxjs/add/operator/scan';
import                               'rxjs/add/operator/filter';
import                               'rxjs/add/operator/switchMap';
import { BehaviorSubject }      from 'rxjs/BehaviorSubject';

export  enum AuthState {
  LOGGED_IN,
  LOGGED_OUT
}

const SESSION_TIMEOUT = 10; // seconds

export class AuthService {
  private timer:         number;
  private tick$:         Observable<number>;
  private countDown$:    Observable<number>;
  private subscriptions:Subscription[];

  constructor(
    private events:Events
  ) {
    this.tick$ =Observable.interval(1000).mapTo(-1);
    this.countDown$ = Observable
      .defer(() => Observable.of(this.timer))
      .merge(this.tick$)
      .scan((acc,curr) => acc + curr)
    this.events.subscribe(RESET_COUNTDOWN, (action:string) => {
      this.resetSessionTimer(action);
    });
  }

  beginCountDown() {
    let sub:Subscription;
    while (this.subscriptions.length > 0) {
      sub = this.subscriptions.pop();
      sub.unsubscribe();
    };
    this.timer = SESSION_TIMEOUT;
    sub = this.countDown$
      .filter(timer => timer >= 0)
      .subscribe(timer => 
        {this.timer = timer;
         if (this.timer === 1) {
           this.logout();
         }
         console.log(this.timer);
        });
    this.subscriptions.push(sub);
  }

  resetSessionTimer(action:string) {
    console.log('AuthService: resetSessionTimer(): ' + action);
    this.beginCountDown();
  } 

  emitAuthState():void {
    this.authManager.next(this.authState);
  }

  private setAuthState(newAuthState:AuthState):void {
    if (newAuthState != this.authState) {
      this.authState = newAuthState;
      this.emitAuthState();
    }
  }
  login(
   clickStream$: BehaviorSubject<any>
  ) {

     this.response$ = clickStream$.switchMap(click =>  {
                      return this.webServiceUtil.testLogin();
                                                      }
                                            );
     this.response$.subscribe((response:Response) => {
          this.setAuthState(AuthState.LOGGED_IN);
      },
     (err:any)          => {
         this.setAuthState(AuthState.LOGGED_OUT);  
     })
  }

  logout() {
      if (this.authState === AuthState.LOGGED_IN) {
         this.setAuthState(AuthState.LOGGED_OUT);
      }
  }
}

RESET_COUNTDOWN事件可能会因更改页面或执行HTTP请求而触发。这将迫使倒计时再次开始,同时只有一个订阅,因此跟踪一系列订阅..你在重置时立即取消。