当access_token过期时,我有401拦截器,成功处理了一个请求。拦截器重新加载令牌,并返回next.handle(customReq)。但是当同时有2个或更多请求并且两个请求都已过期时,我遇到了问题,因为第二个请求尝试再次刷新,但是现在刷新令牌无效。所以...。我试图设置一个标志仅执行一次,并使用自定义的observable返回。 问题是该组件现在是否成功(如果成功或失败),并且我无法删除加载程序。
http拦截器:
return next
.handle(customReq).pipe(
tap((ev: HttpEvent < any > ) => {
if (ev instanceof HttpResponse) {
this.setApiStatus(ApiStatusCode.ACTIVE);
this.interceptorIgnore.removeIgnore(request.url);
}
}),
catchError(resp => {
if (resp instanceof HttpErrorResponse) {
switch (true) {
// Unauthorized
case resp.status === 401:
return this.attemptToRefreshToken(apiRequest, customReq, next);
// More code unnecessary ....
}
}
return throwError(resp);
})
);
attemptToRefreshToken方法:
attemptToRefreshToken(apiRequest: ApiRequest, customReq: HttpRequest<any>, next: HttpHandler) {
const retryRequest = () => {
this.updatingToken = false;
customReq = customReq.clone({
headers: apiRequest.buildHeader()
});
return next.handle(customReq);
};
if (!this.updatingToken) {
this.updatingToken = true;
const tokenRequestData = this.apiAuth.refreshTokenData();
return this.http.request(tokenRequestData.opts.method, tokenRequestData.url, tokenRequestData.opts)
.pipe(flatMap((token: ResponseTokenFormat) => {
ApiAuth.storedToken = token;
this.usersService.queryUsersUsename(ApiAuth.storedUser).then(([user]) => {
if (user && !user.isAdmin) {
this.sessionService.setUserPermissions(user);
}
});
this.tokenUpdated.next();
return retryRequest();
}));
}
return this.tokenUpdated$.pipe(
flatMap(() => retryRequest())
);
}
retryRequest在调用next()时执行,并且运行良好,但从不通知服务对象调用此http请求。返回retryRequest();当我刷新令牌时,令牌可以正常工作,并且该服务可以订阅。
我做错了什么?也许是可观察的?
答案 0 :(得分:0)
我认为您可能必须在 attemptToRefreshToken 中使用 exhaustMap 代替 flatMap em>。
它们如何工作?