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)
}