簡體   English   中英

在執行 stream 的 rest 之前,如何強制 stream 等待 interval() 運算符完成?

[英]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_REFRESHEDTOKEN_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM