我的问题如下:我的 web 应用程序使用了可以过期的身份验证令牌。当它们即将到期时,服务器会发送 401 错误,提示浏览器首先执行令牌刷新请求。我正在使用retryWhen()操作员来处理这种情况。操作员使用以下retryWhen()代码请求新令牌。
public tokenExpired = ({
maxRetryAttempts = 1
}: {
maxRetryAttempts?: number,
} = {}) => (attempts: Observable<any>) => {
return attempts.pipe(
mergeMap((error, i) => {
const retryAttempt = i + 1;
if((error && error.headers && (!error.headers.get("reason-unauthorized") || !(error.headers.get("reason-unauthorized") === "authentication-token-expires-soon"))) || retryAttempt > maxRetryAttempts) {
return throwError(error);
}
return this.requestNewToken().pipe(
concatMap(refreshStatus => {
if(refreshStatus === TokenRefreshStatus.TOKEN_REFRESHED)
return timer(0);
else if(refreshStatus === TokenRefreshStatus.TOKEN_REFRESH_FAILED)
return throwError(error);
else if(refreshStatus === TokenRefreshStatus.AWAIT_REFRESH && this.loggedIn.value){
let maxWaitTimeInMilliSeconds = 4000;
interval(100).pipe(takeWhile(() => !(this.tokenRefreshStatus !== TokenRefreshStatus.AWAIT_REFRESH || maxWaitTimeInMilliSeconds <=0)))
.subscribe(value => {maxWaitTimeInMilliSeconds -= 100;});
if(this.tokenRefreshStatus === TokenRefreshStatus.TOKEN_REFRESHED)
return timer(0);
else return throwError(error);
}
else
return throwError(error);
}));
})
);
}
所以 retryWhen 操作符将tokenExpired作为它的 lambda retryWhen(tokenExpired())。因为几乎可以同时触发多个请求,所以我以这样一种方式编写了代码,即只有第一个请求会触发令牌刷新 http 请求,而通过this.requestNewToken()类似调用的任何其他请求都会从该方法retryWhen获得AWAIT_REFRESH消息。requestNewToken()这样我可以防止对新令牌的多次请求。
当接收到 AWAIT_REFRESH 时,代码必须每 100 毫秒检查一次是否tokenRefreshStatus已更改为TOKEN_REFRESHED或TOKEN_REFRESH_FAILED。它现在可以重复这个更长的时间,然后大约 4000 毫秒。maxWaitTimeInMilliSeconds因此,当达到 0 或更低时,间隔也必须停止重复。之后有一个 if 语句检查是否TokenRefreshStatus等于TOKEN_REFRESHED,如果是,则返回,timer(0)如果不是,则抛出retryWhen操作员收到的原始错误。
我的问题是应用程序不等待间隔代码完成。它只是直接进入 if 语句,导致它总是抛出错误。我认为我不应该订阅间隔,而是应该将其作为一个新的可观察对象返回,该可观察对象执行间隔迭代,然后检查间隔完成后令牌是否已刷新。我只是不知道我该怎么做。
谁能指出我正确的方向?谢谢