我正在使用Angular Material和rxjs 6中的Angular 7.2 MatDialog。令牌过期后,在下一个http请求上,它将弹出对话框,但不会再次提交失败的http请求。 尽管这些建议与我所需的建议略有不同,但我尝试this和this时并不走运。 我所需要的是,在对话框关闭后,它再次提交失败的请求,目前还没有发生。 有人可以协助找到我所缺少的吗?
private refreshingToken: boolean = false;
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(this.setAuthorizationHeader(request))
.pipe(
catchError((error, caught) => {
if (error instanceof HttpErrorResponse) {
if (error.status == 401) {
if (this.refreshingToken) {
return empty();
} else {
this.refreshingToken = true;
setTimeout(() => {
const dialog = this.authenticationService.OpenLoginDialog();
if (dialog) {
const afterClosed$: Subscription = dialog
.afterClosed()
.pipe(
switchMap(() => {
return this.store.select(state => state.AccountState)
.pipe(
map(data => data.accountLoggedIn)
)
}),
switchMap((accountLoggedIn: boolean) => {
if (accountLoggedIn) {
return next.handle(this.setAuthorizationHeader(request));
}
}),
finalize(() => {
this.refreshingToken = false;
if (afterClosed$)
afterClosed$.unsubscribe();
})
)
.subscribe(afterClosedsubscribe => {
console.log({afterClosedsubscribe: afterClosedsubscribe});
});
}
});
}
}
}
return caught;
})
);
}
private setAuthorizationHeader(request: HttpRequest<any>): HttpRequest<any> {
const token = this.tokenService.Get();
if (token != null) {
request = request.clone({
setHeaders: {
Authorization: `${token.tokenType} ${token.accessToken}`
}
});
}
return request;
}
答案 0 :(得分:0)
我认为这是两个switchMaps。
.pipe(
switchMap(() => {
return this.store.select(state => state.AccountState)
.pipe(map(data => data.accountLoggedIn))
}),
switchMap((accountLoggedIn: boolean) => {
if (accountLoggedIn) {
return next.handle(this.setAuthorizationHeader(request));
}
}),
finalize(() => {
this.refreshingToken = false;
if (afterClosed$)
afterClosed$.unsubscribe();
})
)
以此替换上面的代码。
.pipe(
tap(() => {
this.store.select(state => state.AccountState)
.pipe(
switchMap((data) => {
if (data.accountLoggedIn) {
return next.handle(this.setAuthorizationHeader(request));
}
}),
finalize(() => {
this.refreshingToken = false;
if (afterClosed$)
afterClosed$.unsubscribe();
})
);
})
)
顺便说一句,请注意。您执行此过程的方式将永远不会执行原始HTTP请求的订阅。您正在拦截器中使用setTimeout。因此,它不会返回到原始请求者。拦截器只要到达setTimeout就将结束。
如果我对它的理解正确,那么您正在尝试在存在401时恢复会话。如果是这种情况,则可以从此article中获取线索并相应地实现用例。让我知道您是否仍然需要帮助。