我要完成的工作是,根据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);
});
}
观察: 当用户处于登录页面时,我每秒可以看到“ 等待”日志。用户登录后,我开始每秒看到一次“ 查询”日志。一旦会话超时,该用户将被带回到登录页面。此时,我仍然在控制台中看到“ 查询”日志。我想做的是,一旦用户再次登录,请切换回“ 等待”并切换到“ 查询”。
答案 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 {...}
})