Problem
I’m resolving an array of Promises with Promise.all(arrayOfPromises);
I carry on with the promise chain. This is how it seems.
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler();
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
When I try to add a catch statement to handle an individual promise if it fails, Promise.all just gives the first error it detects (ignoring the rest), and then I can’t obtain the data from the rest of the promises in the array (which did not fail).
I’ve attempted to do something similar to…
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler()
.then(function(data) {
return data;
})
.catch(function(err) {
return err
});
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
However, this does not address the problem.
Thanks!
—
Edit:
The answers below were 100% correct; the code was broken due to other factors. This is the answer I came up with, in case anyone is interested…
Server Chain for Node Express
serverSidePromiseChain
.then(function(AppRouter) {
var arrayOfPromises = state.routes.map(function(route) {
return route.async();
});
Promise.all(arrayOfPromises)
.catch(function(err) {
// log that I have an error, return the entire array;
console.log('A promise failed to resolve', err);
return arrayOfPromises;
})
.then(function(arrayOfPromises) {
// full array of resolved promises;
})
};
API Inquiry (route.async call)
return async()
.then(function(result) {
// dispatch a success
return result;
})
.catch(function(err) {
// dispatch a failure and throw error
throw err;
});
Putting the.catch for Promise.all before the.then appears to have accomplished the goal of catching any mistakes from the initial promises while also returning the full array to the next.then.
Thanks!
Asked by Jon
Solution #1
Promise. It’s either all or nothing. It either resolves when all of the promises in the array resolve, or it rejects when one of them fails. To put it another way, it resolves with an array of all resolved values or rejects with a single fault.
Promise is a feature found in several libraries. when, which I believe would wait for all promises in the array to resolve or reject, but I’m not experienced with it and it’s not in ES6.
Your code
I agree with the others in this thread that your solution should work. It should return an array containing a mixture of successful values and errors objects. It’s unusual to pass error objects in the success-path, but I don’t see why not if your code expects them.
The only reason I can think of why it would “not resolve” is that it’s failing in code you’re not showing us and the reason you’re not seeing any error message about this is because this promise chain is not terminated with a final catch (as far as what you’re showing us anyway).
I’ve taken the liberty of taking out the “existing chain” from your example and concluding the chain with a catch. This may not be appropriate for you, but for those reading this, it’s critical to always return or stop chains, or else potential mistakes, including coding errors, will be buried (as I assume happened here):
Promise.all(state.routes.map(function(route) {
return route.handler.promiseHandler().catch(function(err) {
return err;
});
}))
.then(function(arrayOfValuesOrErrors) {
// handling of my array containing values and/or errors.
})
.catch(function(err) {
console.log(err.message); // some coding error in handling happened
});
Answered by jib
Solution #2
NEW ANSWER
const results = await Promise.all(promises.map(p => p.catch(e => e)));
const validResults = results.filter(result => !(result instanceof Error));
FUTURE Promise API
Answered by Solominh
Solution #3
Promise.allSettled is a new method introduced in ES2020 for the Promise type ().
More information can be found in the v8 blog post.
Answered by MosheZada
Solution #4
I built a utility method called executeAllPromises to keep the Promise.all loop going (even if a Promise rejects). This utility function returns a results and errors object.
The idea is that all Promises you pass to executeAllPromises will be wrapped into a new Promise which will always resolve. The new Promise returns an array with two elements. The first spot holds the resolving value (if any) and the second spot keeps the error (if the wrapped Promise rejects).
Finally, executeAllPromises adds up all of the wrapped promises’ values and returns a final object with an array of results and an array of failures.
This is the c
Answered by Benny Neugebauer
Solution #5
As @jib said,
However, you have control over which promises are “allowed” to fail, and we’d like to go on to.then.
For example.
Promise.all([
doMustAsyncTask1,
doMustAsyncTask2,
doOptionalAsyncTask
.catch(err => {
if( /* err non-critical */) {
return
}
// if critical then fail
throw err
})
])
.then(([ mustRes1, mustRes2, optionalRes ]) => {
// proceed to work with results
})
Answered by Herman
Post is based on https://stackoverflow.com/questions/30362733/handling-errors-in-promise-all