遅延と試行回数制限のある RXjs RetryWhen を作成する方法 質問する

遅延と試行回数制限のある RXjs RetryWhen を作成する方法 質問する

retryWhen を使用して、失敗したときに再試行する API 呼び出し (angular4 を使用) を実行しようとしています。500 ミリ秒遅延して再試行します。これは次のコードで実現できます。

loadSomething(): Observable<SomeInterface> {
  return this.http.get(this.someEndpoint, commonHttpHeaders())
    .retryWhen(errors => errors.delay(500));
}

しかし、これは永遠に試行され続けます。これを、たとえば 10 回に制限するにはどうすればよいでしょうか?

ありがとう!

ベストアンサー1

たとえば、再試行を 10 回だけ行いたい場合は、再試行信号に制限を適用する必要があります。

loadSomething(): Observable<SomeInterface> {
  return this.http.get(this.someEndpoint, commonHttpHeaders())
    .retryWhen(errors => 
      // Time shift the retry
      errors.delay(500)
            // Only take 10 items
            .take(10)
            // Throw an exception to signal that the error needs to be propagated
            .concat(Rx.Observable.throw(new Error('Retry limit exceeded!'))
    );

編集

コメント投稿者の中には、最後にスローされるエラーを確実にする方法を尋ねる人がいました。答えは少しわかりにくいですが、強力です。フラット化マップ演算子 (concatMap、mergeMap、switchMap) のいずれかを使用して、どのインデックスにいるかを確認するだけです。

注: 将来の保証のために新しい RxJS 6pipe構文を使用します (これは RxJS 5 の後のバージョンでも使用できます)。

loadSomething(): Observable<SomeInterface> {
  const retryPipeline = 
    // Still using retryWhen to handle errors
    retryWhen(errors => errors.pipe(
      // Use concat map to keep the errors in order and make sure they
      // aren't executed in parallel
      concatMap((e, i) => 
        // Executes a conditional Observable depending on the result
        // of the first argument
        iif(
          () => i > 10,
          // If the condition is true we throw the error (the last error)
          throwError(e),
          // Otherwise we pipe this back into our stream and delay the retry
          of(e).pipe(delay(500)) 
        )
      ) 
  ));

  return this.http.get(this.someEndpoint, commonHttpHeaders())
    // With the new syntax you can now share this pipeline between uses
    .pipe(retryPipeline)
}

おすすめ記事