为什么switchMap内部的时间间隔停止发出值

时间:2019-02-04 17:31:55

标签: javascript angular rxjs

我想使用rxjs轮询应用程序中的用户会话,但仅当用户会话处于活动状态时。

我将用户会话存储在会话存储中。当我们打开应用程序时,它为空,当我们登录时,它会被刷新,并且它所连接的BehaviourSubject也将被更新。然后,我开始一个rxjs间隔,直到会话期满,以便随后可以注销。

sessionUser$ = new BehaviorSubject<UserAuthSession>(this.getSessionUser());

private pollSessionTimeout(): void {
    this.sessionUser$
      .pipe(
        filter(user => {
          return user !== null;
        }),
        switchMap(() => interval(1000)),
        skipWhile(this.isAuthenticated),
        take(1)
      )
      .subscribe(x => {
        console.log('Poll is deleting session', x);
        this.deleteSession();
        this.router.navigate(['auth/login']);
      });
}

我希望当我们第一次启动该应用程序且没有用户时,间隔不会运行。工作正常!

我希望登录后会发送一个新的非null sessionUser事件,我们开始间隔直到isAuthenticated(检查会话是否到期)为false,然后仅使用1个事件注销。工作正常!

我希望,如果我手动注销,将发送一个新的null sessionUser事件,该事件将停止间隔。这是行不通的,因为它仍然要经过一次isAuthenticated并再次调用一次才能删除。不理想,但我可以解决。更大的问题是,当我再次登录时,间隔仅运行4次(为什么?),然后停止运行并检查isAuthenticated。

知道为什么会这样吗?您是否建议另一种方法?

1 个答案:

答案 0 :(得分:2)

我不确定您想要的逻辑,但是似乎您可以重新构建已经拥有的链。然后,如果您希望interval停止发射,则可以从EMPTY返回switchMap

import { EMPTY } from 'rxjs';
...

this.sessionUser$
  .pipe(
    switchMap(user => {
      if (user) {
        return interval(1000).pipe(
          skipWhile(this.isAuthenticated),
          take(1)
        );
      } else {
        return EMPTY;
      }
    })
  ).subscribe(...);