Promise.all for Rejections and Resolves
Promises have been an incredible addition to JavaScript; they save us callback hell, make coding async more maintainable, and and allow us to keep track of multiple async processes at a time. Promise.all
comes to mind, allowing us to react when multiple promises have been resolved. Unfortunately Promise.all
only resolves when all promises are resolved, so if any of the promises fail, the catch
is called instead of then:
Promise.all([ Promise.resolve(1), Promise.reject(0) ]) .then(() => { console.log('resolved!'); }) .catch(() => { console.log('failed!') }); // >> failed!
This is a problem if you want the same functionality to be executed regardless of if any promise in the array is rejected. You could provide the same function to then
and catch
but that could lead to maintenance issues and occasional "WTF IS THIS?!" comments from other engineers.
So what should we do when we want Promise.all
to trigger functionality regardless of any rejections? Jake Archibald has the answer:
Promise.all(promises.map(p => p.catch(() => undefined)));
Each promise's catch
callback returns undefined
which allows the promise's failure to be handled as success. To prove it works, consider this snippet:
Promise.all([ // Resolves Promise.resolve(1), // Rejects after 2 seconds new Promise((resolve, reject) => setTimeout(() => reject(1), 2000)) ].map(p => p.catch(() => undefined))).then(() => console.log('done!')); // >> done!
Despite the second promise being rejected, the Promise.all
then
is called! In the future we'll be able to use Promise.prototype.finally
to more easily handle success and failure.
Thank you to Jake for this awesome trick!
Have you tried RQ, from our famous and beloved Douglas Crockford, a great (and tiny) async library?
http://www.rq.crockford.com/
This was on StackOverflow about a year ago http://stackoverflow.com/a/36115549/1253312
Howdy David,
Nice find! I was really struggling with this until I found this method of handling errors.
Rather than just leaving the rejected promise as undefined, if you add in a flag in the reject event, you can catch the error message cleanly and process in the then function, eg:
Matt
Hello, I have these two query using promise.using, with bluebird, I can only execute one or the other, how do I create a promise all to execute the two function promise and also other function.
I have:
The method explained in the article would masquerade errors and unhandled exceptions.
This post should be updated with the solution in here:
https://stackoverflow.com/a/32979111/3221029
Plus
Promise.finally
is already supported.Using
Promise.finally
will not help you there, as it does not suppress errors.Meaning – the
Promise
will still throw after you’ve chained it with afinally
call.Using
Promise.catch
is still your best bet!