I have a function which gets given a list of ids and then maps
over that list and calls an API for each one:
let fullDetails: Array<any> = [];
ids.map(async (id) => {
try {
const result = await api.getFullDetails(id);
if (result.data) fullDetails.push(result.data);
} catch {
// Handle error
}
});
The problem I'm having is that sometimes the getFullDetails
function will return an error just because the record it's looking for doesn't exist. But, I don't really care if the record doesn't exist (to be honest, I don't really care about any errors here) - I'm happy to just skip that one and move on to the next. No matter what I do, though, my code seems to bail out at that point if the result is an error.
I've tried leaving out the try-catch
block, but then I get a 'Possible unhandled Promise rejection' error and fullDetails
remains empty (although I know for sure that one of the ids worked ok).
I also tried rewriting to use Promise.all
, like this:
let results = ids.map((id) =>
api.getFullDetails(id),
);
Promise.all(results)
.then((result) => {
console.log(result);
})
.catch((error) => { console.log('Error')});
but again, it goes into the catch block if there's any kind of error. Again I tried leaving out the catch block here, but then I got the 'Possible unhandled Promise rejection' error again, and the result was never shown.
Is there a way to handle this (apart form rewriting the API to not return an error)? Basically I just don't want to check for errors at all, and just ignore them if they occur.
The proper way to use map with async is to use one of the Promise's methods.
It's better to choose Promise.allSettled()
rather than Promise.all()
in your case. Because, according to MDN,
In comparison, the Promise returned by Promise.all() may be more appropriate if the tasks are dependent on each other, or if you'd like to immediately reject upon any of them rejecting.
Meaning the former case won't reject promises and stop the program execution.
Note that the allSettled()
returns an object with two of this three properties:
[{
reason: "Id must be non-negative",
status: "rejected"
}, {
status: "fulfilled",
value: 2
}]
The first case happens when the Promise is rejected and the second when it's fullfiled.
Promise.allSettled(ids.map((id) => api.getFullDetails(id))).then(x => {
let fullDetails = x.map(({value})=>value).filter(Boolean)
console.log(fullDetails)
})
As seen in this working example.