Reputation: 3
I need to retry a specific API call for about three times when there is a 502 bad gateway error. The retry may happen with slightly incremental delays. This is the code in the component.
some.component.ts
someMethod() {
let attempt = 0;
this.someService.AppendSubject(this.subject)
.pipe(retryWhen(errors => errors.pipe(
tap(error => this.retryApi(error, ++attempt, 'Server busy. Retrying request', this.subject))
)))
.subscribe(response => {
//do something with response
});
}
retryApi(error: any, attempt: number, retryMessage: string, data?: any) {
delay(this.duration*attempt)
//show toast with retryMessage
if (attempt > this.retryLimit) {
//show some message
if (data)
this.notifyFailure(data);
throw error;
}
}
notifyFailure(data: any) {
this.someService.notifyFailure(data);
}
some.service.ts
public AppendSubject(data: any) {
return this.http.post<any>(`{env.api}/appendsubject/`, data);
}
public notifyFailure(data: any) {
return this.http.post<any>(`{env.api}/notifyfailure/`, data);
}
Is this due to how I am doing/not doing the catching of errors in the retry? How do I properly catch errors in the above piece of code and not obstruct or kill the further notifyFailure call?
Note: I am not doing this in the interceptor currently since this is only for specific APIs at this point. I am writing the retry handler in the component and not at the some.service.ts
level since I didn't know how to do that and while showing appropriate toasts and popups in the component.
Upvotes: 0
Views: 1120
Reputation: 3
Based on AlexanderFSP's answer, I modified my code to catch errors this way.
.pipe(retryWhen(errors => errors.pipe(
tap(error => this.retryApi(error, ++attempt, 'Server busy. Retrying request', this.subject)),
catchError(() => {
this.notifyFailure(data);
return EMPTY;
})
)))
.subscribe(response => {
//do something with response
});
It is working for now.
Upvotes: 0
Reputation: 662
Good day! I prefer to use such approach:
Your service:
getSomething(retryCount: number = 0, retryInterval: number = 1000) {
return this.http.get(this.getSomethingUrl).pipe(
retryWhen((error: Observable<any>) => error.pipe(
delay(retryInterval),
take(retryCount)
))
);
}
In component:
this.service.getSomething(3, 2000).subscribe(response => {
// Handle success
}, error => {
// Here you can send a request to your BE (triggers only after 3 failed requests in this case), to notify about the occurred error
// Also you can do it in your pipe using `catchError` rxjs operator
});
Upvotes: 1