Reputation: 369
Information needed: Using NodeJS framework, Promises.all used with API calls only so asynchronous code
So the bases of my problem lies where I need to create two API calls, let's call them A and B. It is guaranteed that A will either return data or a 404 and B will either return an empty array, data or a 404 (but here the 404 means invalid input, while in API call A, it actually means no resource found). My question is that if A does return a 404, the Promise.all will reject and jump into the catch block as it would normally.
My desired functionality is, if API call A returns a 404, I want API call B to continue and retrieve that data, continuing with my code. Is there a way to distinguish or even separately catch the errors thrown by the two API calls and then carry on if one resolves??
Sample code currently looks like this:
function(param) {
const A = apiCallA();
const B = apiCallB();
return Promise.all([A, B])
.then( ([resA, resB]) => {
// If resA is null, catch the error but continue with
// resB. If this is null also Promise.reject('both API calls failed')
// else if both resA && resB != null, do some stuff and resolve
})
.catch( (err) => {
// Here is where my question lies. The err object can be either from API call A or B.
// How would I distinguish this?
});
}
Upvotes: 0
Views: 1445
Reputation: 707158
There are several options.
You can catch the error from API call A before the Promise.all()
and turn it into a successful request but tagged approrpiately, allowing the Promise.all()
to finish.
You can use Promise.allSettled()
to get both results, regardless of success or failure.
For the first option, you could put a .catch()
handler on apiCallA()
that will turn any rejection into a resolve, but will resolve with the error object which you can then later check if you need to:
function(param) {
const A = apiCallA().catch(err => { return {err} });
const B = apiCallB();
return Promise.all([A, B]).then( ([resA, resB]) => {
// you can check if resA succeeded here
if (resA instanceof Error) {
// resA actually failed
console.log(resA);
}
}).catch( (err) => {
// you would only get here if resB failed
});
}
For the second option, you use Promise.allSettled()
:
function(param) {
const A = apiCallA();
const B = apiCallB();
return Promise.allSettled([A, B]).then( ([resA, resB]) => {
// check both resA.status and resB.status
if (resA.status === "fulfilled") {
console.log(resA.value);
}
if (res === "fulfilled") {
console.log(resB.value);
}
});
}
Upvotes: 1