Reputation: 493
I am trying to implement an httpService where we have 3 Rest API endpoint. If the first API return a success code then I don't want to call the next end point but i case of error i want to try second or third. I have written my code like
import { of, throwError } from 'rxjs'; import { catchError, mergeMap } from 'rxjs/operators';
this.httpService
.post(`${primary_system}?id=${params.id}`)
.pipe(
catchError((primaryError) => {
if (!!secondary_system) {
return this.httpService
.post(`${secondary_system}?id=${params.id}`)
.pipe(
catchError((secondaryError) => {
if (!!tertiary_system) {
return this.httpService.post(`${tertiary_system}?id=${params.id}`);
}
return of(secondaryError);
})
);
}
return of(primaryError);
})
);
certainly the will be a way to flattern these nested calls. I think this is bad practice to pipe Observables like this. Any better solution?
Upvotes: 1
Views: 71
Reputation: 17762
You do not need to embed the second catchError
into the closure of the first catchError
.
In other words you can do something like this
this.httpService
.post(`${primary_system}?id=${params.id}`)
.pipe(
catchError((primaryError) => {
if (!!secondary_system) {
return this.httpService
.post(`${secondary_system}?id=${params.id}`)
);
}
return of(primaryError);
}),
// here you catch an error that is generated by the call to the
// secondary system
catchError((secondaryError) => {
if (!!tertiary_system) {
return this.httpService.post(`${tertiary_system}?id=${params.id}`);
}
return of(secondaryError);
})
);
You could also make the code maybe more readable by introducing 2 functions that represent the calls to the secondary and tertiary systems, like this
// this function returns an Observable that represents the call to the
// secondary system if it catches an error coming from upstream
function callSecondIfFirstFail(id: any) {
return pipe(
catchError((primaryError) => {
if (!!secondary_system) {
return this.httpService.post(`${secondary_system}?id=${id}`));
}
return of(primaryError);
}),
)
}
// this function returns an Observable that represents the call to the
// tertiary system if it catches an error coming from upstream
function callThirdIfSecondFail(id: any) {
return pipe(
catchError((secondaryError) => {
if (!!tertiary_system) {
return this.httpService.post(`${tertiary_system}?id=${id}`));
}
return of(secondaryError);
}),
)
}
// this is then how the code that performs the, possible, three calls
// would look like
this.httpService
.post(`${primary_system}?id=${params.id}`).pipe(
callSecondIfFirstFail(params.id),
callThirdIfSecondFail(params.id)
)
This stackblitz tries to represent this idea.
Upvotes: 3