In my Angular app, I want to make an HTTP call to a backend server. To make it more resilient I added an interceptor to implement the retry pattern.
I used to take advantage of RxJS's retryWhen
operator, but that is now deprecated so I do this:
return next.handle(copiedRequest).pipe(
retry({
count: 5,
delay: 1000,
}),
catchError((error: HttpErrorResponse) => {
if (error.status === 0) {
// Server not responding, so stuff
}
return throwError(() => error);
})
);
The problem is that this now works for all my HTTP response statuses, while sometimes when the server returns a certain status code, you know retrying makes no sense. Is there a way to add a filter to the retry so it can check whether or not to actually do the retry?
What you want can be achieved with the delay
param of the retry
operator:
next
.handle(copiedRequest)
.pipe(
retry({
count: 5,
delay: (error: HttpErrorResponse, retryCount: number) => {
// not using it for the demo you could also dynamically
// change the behavior based on the retryCount param
switch (error.status) {
// retryable error status
case 0:
case 1:
// retry
return of(null);
default:
// for the rest, we just forward the original error
return throwError(() => error);
}
},
})
)
Here's a Stackblitz demo that you can play with and where I've also built up some mocks so that you can verify the fact that the original request is retried several times.
CF the console output on Stackblitz:
Request made: 0 // first one
Request made: 1 // second one
Request made: 2 // third one
An error was caught: Error: Some mocked error // received a non retryable error and forwarded it