I am trying to make an API call (using angular4), which retries when it fails, using retryWhen. I want it to delay for 500 ms and retry again. This can be achieved with this
You need to apply the limit to the retry signal, for instance if you only wanted 10 retries:
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!'))
);
EDIT
Some of the commenters asked how to make sure that the last error is the one that gets thrown. The answer is a bit less clean but no less powerful, just use one of the flattening map operators (concatMap, mergeMap, switchMap) to check which index you are at.
Note: Using the new RxJS 6 pipe
syntax for future proofing (this is also available in later versions of 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)
}
Use
.retry(3)
Repeats the source observable sequence the specified number of times or until it successfully terminates.
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/retry.md