I'm trying to implement an api call that will be
- retried few times if there is any errors
- after a specific time delay
- with some other condition check like - if returned success response json has any field null, I'll retry the api call
I tried to implement what is mentioned here - Rxjs Retry with Delay function
Following is my code segment
Api call
delay = 5000;
retryCount = 5;
return this.httpClient.post(http://localhost:8080/info,JSON.stringify(data))
.pipe(
retryWhen(errors =>
errors.pipe(
delay(this.delay),
take(this.retryCount),
tap(val => {
console.log('Retrying.');
}),
concatMap(() => Observable.throw(new Error('Retry limit exceeded!')))
)
)
);
Processing the response
this.searchService.searchInfo(param1, param2).subscribe(data => { this.handleSuccessResponse(data) }, (error) => {
if (error) {
// Handle specific error here
handleErrorResponse(error);
}
});
handleSuccessResponse(data){
// handle success response here
}
handleErrorResponse(error){
// Handle generic error here
}
The issue I am getting, before retrying for 5 times as I mentioned in the code, the exception in the concatMap is getting throwed. What I am missing here?
I'm using RxJS 6.4 with Angular12
CodePudding user response:
I went through the learnRxjs
docs and got this generic method, which seems to satisfy your requirement!
import { Observable } from 'rxjs/Observable';
import { _throw } from 'rxjs/observable/throw';
import { timer } from 'rxjs/observable/timer';
import { mergeMap, finalize } from 'rxjs/operators';
export const genericRetryStrategy =
({
maxRetryAttempts = 3,
scalingDuration = 1000,
excludedStatusCodes = [],
}: {
maxRetryAttempts?: number;
scalingDuration?: number;
excludedStatusCodes?: number[];
} = {}) =>
(attempts: Observable<any>) => {
return attempts.pipe(
mergeMap((error, i) => {
const retryAttempt = i 1;
// if maximum number of retries have been met
// or response is a status code we don't wish to retry, throw error
if (
retryAttempt > maxRetryAttempts ||
excludedStatusCodes.find((e) => e === error.status)
) {
return _throw('Retry limit exceeded!');
}
console.log(
`Attempt ${retryAttempt}: retrying in ${
retryAttempt * scalingDuration
}ms`
);
// retry after 1s, 2s, etc...
return timer(retryAttempt * scalingDuration);
}),
finalize(() => console.log('We are done!'))
);
};
CodePudding user response:
case 1
res === null
alwaysrepeat
(delay 500ms)- Just
retry
API Error 5 times (delay 500ms)
api$.pipe(
repeat({ delay: 500 }),
skipWhile((res) => res === null),
take(1),
retry({ count: 5, delay: 500 })
).subscribe(observer);
Repeat HTTP call until the desired value is returned with RxJs
case 2
res === null
API Error = 5 times (delay 500ms)
api$.pipe(
skipWhile((res) => res === null),
throwIfEmpty(),
retry({ count: 5, delay: 500 })
).subscribe(observer);