[英]How do I wait for an observable to update before executing more code?
[英]How do i force a stream to wait for the interval() operator to complete before executing the rest of the stream?
我的問題如下:我的 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 語句,導致它總是拋出錯誤。 我認為我不應該訂閱間隔,而是應該將其作為一個新的可觀察對象返回,該可觀察對象執行間隔迭代,然后檢查間隔完成后令牌是否已刷新。 我只是不知道我該怎么做。
誰能指出我正確的方向? 謝謝
我的問題是應用程序不等待間隔代碼完成。
發生這種情況是因為間隔創建了一個異步的可觀察對象。 我會嘗試讓您的 refreshStatus function 異步調用 await 當您希望它等待時(即:將您的間隔包裝在 promise 中等待它):
concatMap(async refreshStatus => {
.
.
.
function checkit(){
return new Promise((res, rej)=>{
interval(100).pipe(takeWhile(() =>{
if(!(this.tokenRefreshStatus !== TokenRefreshStatus.AWAIT_REFRESH || maxWaitTimeInMilliSeconds <=0)){
return true;
}
else{
res(true);
return false;
}
}))
.subscribe(value => {maxWaitTimeInMilliSeconds -= 100;});
});
}
await checkit();
.
.
.
})
我希望這可以幫助您解決問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.