RxJS 系列 – Error Handling Operators

前言

前幾篇介紹過了 

Creation Operators

Filter Operators

Join Creation Operators

這篇繼續介紹 Error Handling Operators.

 

參考

RxJS 錯誤處理 Operators (1) - catchError / finalize / retry / retryWhen

Docs – Error Handling Operators

 

Observable and Subscriber Handler Error

Observable 的流程是 : Observable init > pipe > subscribe

不經過 pipe 的情況下, 處理 error 的方式如下:

const obs = new Observable(subscriber => {
  subscriber.error('error message');
  // throw 'error message'; // throw 也是可以
});
obs.subscribe({
  error: errorMessage => console.log(errorMessage), // error message
});

簡單明瞭.

 

catchError

catchError 是 pipe 階段的 error handle. 它是 operator 來的.

catch error and change to succeeded

const obs = new Observable(subscriber => {
  subscriber.error('error message');
});
obs
  .pipe(
    catchError(error => {
      console.log(error); // error message
      return of('succeeded');
    })
  )
  .subscribe({
    next: value => console.log(value), // succeeded
    error: errorMessage => console.log(errorMessage), // won't call
  });

catchError 接收到 error 後, 可以有幾個處理方式. 上面這個是返回一個 "成功" 的 Observable, 這樣 error 就不會在傳下去了. 

catch error and re-throw

catch error 然後繼續往下 throw error,

throwError 方法之前介紹過了, 它是 Creation Operators 的一員.

catchError(error => {
  return throwError(() => 're-throw error');
  // throw 're-throw error'; // 用 throw 也可以
})

小結

總之, catchError 要返回一個 Observable, 可以是 succeeded 或者是 error

catchError(error => {
  if (Math.random() < 0.5) {
    return throwError(() => 're-throw error');
    // throw 're-throw error'; // 用 throw 也可以
  } else {
    return of('succeeded');
  }
})

catch error and retry

除了 succeeded 和 error, 還有一種處理方式是 retry. 所謂 retry 就是 unsubscribe 當前的 stream, 重新 subscribe Observable 得到新的 stream (舊的 Observable 會 displose, 新的會 init)

catchError((error, caught) => {
    return caught;
})

返回 catchError 的第二個參數 caught 就表示要 retry. retry 可能會導致死循環的哦.

所以必須要有條件, 避開死循環, 比如:

catchError((error, caught) => {
  if (Math.random() < 0.5) {
    return caught; // retry
  } else {
    return of('succeeded');
  }
})

delay retry

catchError((error, caught) => {
  return timer(2000).pipe(switchMap(() => caught));
})

返回一個 delay 的 Observable 就可以延後 retry 了. 這裏用了 switchMap 把 timer 的值換成了 caught observable. (這個 operator 我還沒有介紹過的)

retry count

要計算 count 只能開一個外部的 variable 做記入. 或者封裝一個自定義 operator. 但更簡單的方法是直接用 RxJS 提供的 retry 和 retryWhen operator. 下面會介紹.

 

retry

用 catchError + caught 實現 retyr 太費勁了, 所以 RxJS 封裝了 retry operator

retry({
  count: 3,
  delay: 2000,
  resetOnSuccess: false,
})

count 聲明可以 retry 多少次

delay 聲明 retry 的間隔時間, 有時候 error 是因爲 server 繁忙, 只要等 1,2 秒在 retry 發 ajax 就可以解決了.

此外 delay 還支持更復雜的 config. 通過判斷 error 和 retryCount 來決定要 delay 多少秒.

我們甚至可以返回 click$ 讓 user 點擊觸發 retry. 

也可以直接返回 throwError 結束 retry (即便還沒有 hit 到 max retry count), 靈活就對了

delay: (error, retryCount) => timer(2000 * retryCount)

resetOnSuccess 聲明當 retry 成功以後是否要 reset retry count. 默認值是 false, 通常 reset 是正確的, 所以一般我都是 set 成 true.

 

retryWhen

已經廢棄了, 改用 retry + delay option 實現吧.

 

 

一句話總結

catchError : 在 pipe 中 catch error, 3中處理, 成功, 繼續 error, retry

retry : 用 catchError 做 retry 太費勁就有了 retry operator

retryWhen : 廢棄了, 改用 retry + delay option 實現.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章