Post

Promise All

Modifying the behavior of Promise.all()

By now, as a JavaScript developer, you have probably used the Promise API at some point in your project. Promise offers a good alternative to using callbacks when dealing with asynchronous operations. Now, if you have a collection of promises you want all to be resolved and to aggregate the results in one promise, there’s Promise.all() and it works like this:

Promise.all(), by design, has a fail-fast behavior. It means it will reject as soon as one of the element has rejected.

But what if you expect some promises to reject and want to get as many resolved results as possible? One way to do it is to wrap your promises around another promise that will never reject.

The problem with this approach is that it’s ugly (citation needed). And now you lose out on the mechanism to respond to errors (since you silently ignore all of the rejected). Doing this will potentially result in a holed collection where you have to filter out failed promises.

A better alternative is to come up with your own promise aggregator function. There are many possible approaches and here’s the most basic one I’d like to propose:

Let’s dissect this a bit. First, I want a way to iterate over the given array of promises. This can be done in different ways. For example, I can use Array.prototype.forEach(), conventional for…loop, or I can try the Iteration protocol.

Iteration protocol is implemented array prototype. Once you have retrieved the iterator, you get:

iterator.next() which returns the next element in the array and is used to iterate over each element iterator.done to check if you have gone through every element yet iterator.value to access the value of the element returned from calling next() You can look up more info regarding the Iteration protocol from MDN’s documentation here (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)

Next, I need a way to keep track of each promises resolving progress. I do this using a simple counter “resolving”.

The gist of the whole thing is, resolve each promises while keeping track of the progress. Once all promises are resolved, the aggregated results are ready. So resolve it as an array.

With this approach, you can control the behavior of how it should handle different cases. You can have it return null when the promise reject(), or you can simply return as many successfully resolved elements as possible, or you can have it reject as soon as any of the promises reject(), just like the default behavior of Promise.all() too!

credit to Sindre Sorhus’s p-map module (github.com/sindresorhus/p-map) that get me started.

This post is licensed under CC BY 4.0 by the author.