I've 2 api service calls that I zip into one observable:
const firstAPIrequest = this.firstApi.getData();
const secondAPIrequest = this.secondApi.getData();
const combined = zip(firstAPIrequest, secondAPIrequest);
I currently map these to return an array:
combined.pipe(
map((res) => {
return [res[0], res[1]) // just an example
}
);
Then I use it as a subscription in a different component
combined.subscribe(
(res) => this.handleData(res),
(err) => {
console.debug('Fetch failed', err);
}
)
In this case, if one of the API request failed it will show an error, but I would like to check in between which one failed, for example; if request1
returned data and request2
failed I would still return the data from request1
I've tried catchError
but I don't think I can get the data in this function
combined.pipe(
catchError((err) => ...), // how would I catch the data before it throws an error?
map((res) => {
return [res[0], res[1]) // just an example
}
);
CodePudding user response:
To handle errors from each source individually, the catchError
must be piped into each of them individually. catchError
must return an observable, so we'll use RxJS of
function for it.
import { of, catchError } from 'rxjs';
const handleError = (error: any) => of({error: error});
const firstAPIrequest = this.firstApi.getData().pipe(
catchError(this.handleError)
);
const secondAPIrequest = this.secondApi.getData().pipe(
catchError(this.handleError)
);
const combined = zip(firstAPIrequest, secondAPIrequest);
Now in the subscription you could check if the response is valid or an error.
combined.subscribe(
([res1, res2]) => {
if (!!res1.error && !!res2.error) {
// both API calls threw error
} else if (!!res1.error) {
// `firstAPIrequest` threw error
} else if (!!res2.error) {
// `secondAPIrequest` threw error
} else {
// both returned responses
}
}
);
Note: this assumes the actual response doesn't contain a property error
. If so replace the error
property in the handleError
function with something else.
CodePudding user response:
you have to catch error on both of the sources, because if you caught the error after combining, the combination stream stops after the first error. for example:
const replaceErrorWithNull = catchError(() => of(null));
const firstAPIrequest = this.firstApi.getData();
const secondAPIrequest = this.secondApi.getData();
const combined = zip(
firstAPIrequest.pipe(replaceErrorWithNull),
secondAPIrequest.pipe(replaceErrorWithNull)
);
with this approach null will be in place of data from API that errored