Reputation: 239
I've got a chain of observables. Here is the piece of code:
//get dynamic tree
flatMap(res => this.dynamicReportId !== null ? this.reportService.getDynamicTree(this.dynamicReportId) : of({})),
tap(res => this.dynamicTree = res),
//get dynamic report
flatMap((res) => this.dynamicReportId !== null ? this.reportService.getDynamicReport(this.dynamicReportId) : of({})),
However when I got 500 API error from the first request(get dynamic tree), the chain stops and never enters the second flatMap(dynamic report).
Here is the function this.reportService.getDynamicTree()
:
get(path: string, params: HttpParams = new HttpParams()): Observable<any> {
return this.http.get(`${environment.apiBaseUrl}${path}`, {headers: this.setHeaders(true), params: params}).pipe(
catchError(error => this.processError(path, error)),
map((res: Response) => res));
}
where this.processError
returns observableThrowError(res);
What should I return in case of error to continue the chain? Or is the reason in other things?
Upvotes: 5
Views: 917
Reputation: 31825
In case of an error, an Observable
completes, so if you want to return a new Observable
after an error occurs, you have to use the catchError
operator like this:
//get dynamic tree
flatMap(res => this.dynamicReportId !== null ? this.reportService.getDynamicTree(this.dynamicReportId) : of({})),
tap(res => this.dynamicTree = res),
catchError(() => of({})),
//get dynamic report
flatMap((res) => this.dynamicReportId !== null ? this.reportService.getDynamicReport(this.dynamicReportId) : of({})),
The tap
operator safely doesn't execute the callback and just forwards errors when they occur so that will assign this.dynamicTree
only in case of a success.
If you want to handle the error in the service instead of the component, you have to return something else than observableThrowError(res);
from processError
(for example of({})
) but that will execute the tap
callback and assign this.dynamicTree
which is probably an unwanted behavior.
Upvotes: 6
Reputation: 1617
First of - continuing the chain kind of defeats the whole concept of a chain. However, I think this issue should be resolveable by having some fairly simple chain iterator and handling errors thrown by HttpClient and service.
I created a StackBlitz example with my solution: https://stackblitz.com/edit/chain. For simplycity, the chain returns data in { result: any, error: any }[]
. Of course you will be able to do pretty much anything in terms of piping operators to adjust the result.
Ideally, the observableChain
functionality would be separate and handling the empty results as you need it to - in your case instead of returning { result: any, error: any }[]
it would return {}
on error response and log the error.
Upvotes: 2