在两个流之间进行来回切换(Observables)

时间:2019-06-18 17:43:13

标签: angular stream rxjs observable

我要完成的工作是,根据cookie的存在情况跟踪用户的会话。如果会话超时,我将自动注销用户。为了实现这一点,我正在等待cookie首先出现,即等待用户进行有效的API调用。然后,我开始查询cookie,直到不再存在为止。下面的代码是第一次为我工作。但是,在订阅了第一个流之后,当用户开始新会话而不重新加载浏览器时,我无法恢复它。

代码:

private _setupSession(): void {

    const waitForCookie = interval(1000)
      .pipe(
        tap(() => {
          console.log('waiting');
        }),
        switchMap(() => of(this._cookieService.get(COOKIE_STRING))),
        filter((val) => !!val),
        take(1));

    const queryCookie = interval(1000)
      .pipe(
        tap(() => {
          console.log('querying');
        }),
        switchMap(() => of(this._cookieService.get(COOKIE_STRING))),
        distinct());

    waitForCookie.pipe(concatMap(() => queryCookie))
      .subscribe(
        (val) => {
          if (!val) {
            this._router.navigate([''], {queryParams: {sessionTimedOut: true}});
          }
        },
        (err) => {
          console.log(err);
        });
  }

观察: 当用户处于登录页面时,我每秒可以看到“ 等待”日志。用户登录后,我开始每秒看到一次“ 查询”日志。一旦会话超时,该用户将被带回到登录页面。此时,我仍然在控制台中看到“ 查询”日志。我想做的是,一旦用户再次登录,请切换回“ 等待”并切换到“ 查询”。

2 个答案:

答案 0 :(得分:1)

如果我了解您的要求,那么这就是您想要做的:

this._cookieService.get()方法中监视cookie,如果该值为null/empty/undefined,则引导用户登录页面并保持每1秒监视this._cookieService.get()的值。 / p>

如果我的理解是正确的,那么:

我认为您可以通过仅使用以下一种流来实现:

const queryCookie = interval(1000)
      .pipe(        
        switchMap(() => of(this._cookieService.get(COOKIE_STRING))),
        //skipwhile will ensure to avoid timeout on starting of the page/app
        skipWhile(cookie => !cookie)
      );

queryCookie
      .subscribe(
        (val) => {
          if (!val) {
            this._router.navigate([''], {queryParams: {sessionTimedOut: true}});
          }
        },
        (err) => {
          console.log(err);
        });

顺便说一句-我建议不要每1秒查询一次。我猜您的应用程序可能以某种方式将cookie在localStorage中设置为null / empty / undefined。如果是这样,则可以通过使用Subject / BehaviorSubject使代码更好一些,并且可以避免查询1秒。这只是一个观察,因为我不知道您的应用程序设计。

答案 1 :(得分:1)

检出cookies.onChanged api。您可以使用fromEventPattern设置Observable,然后根据更改执行操作。一个实现可能看起来像这样:

const signedIn$ = fromEventPattern(
 handler => browser.cookies.onChanged.addListener(handler),
 handler => browser.cookies.onChanged.removeListener(handler)
).pipe(
  map(changeInfo => changeInfo.cookie.name === 'myCookie' && changeInfo.removed)
 )
);

signedIn$.subscribe(signedIn => {
  if (signedIn) {...}
  else {...}
})