How to implement `Promise.all`?

Jason Yu on March 27, 2018

Recently, I was challenging myself to implement some of the core APIs in Javascript. And Promise.all turns out to be a quite interesting one. If ... [Read Full]
markdown guide
 

Nice article Jason!

Just an FYI — the examples given try to overwrite a const, so that won't run.

I think you can make your first example terser as well without implementing the counter (unless you liked it for perf)

Such as:

Promise.all = (ps) => new Promise((res) => {
    let results = []; 
    ps.forEach((p, i) => p.then(result => {
        results[i] = result;
        if (results.length == ps.length) return res(results);
    }))
});
 

Oops, another typo spotted! It should have been a let instead. Thanks for pointing it out.

I do think the counter is needed tho as we cannot guarantee the order of which the promises finish. So if the last promise doesn't finish the last, the results array will not be fully populated because of this:

const xs = [];
xs[6] = 3:
xs.length === 7; // true
 

I just realized that only the first solution (using counters) works like the browser's Promise.all. The problem with the other solutions occurs when one of the individual promises -- not the first one -- rejects before the promises before it resolve. In this case, Promise.all will wait and only reject once all the other promises resolve. In addition, the browser will throw a UnhandledPromiseRejectionWarning.

Only the first solution will not wait to reject any individual promise.

 

this is true. thank you! it is a good shout!

 

Awesome article. Here is my ES2018 variant with async iterator:
(github.com/tc39/proposal-async-ite...)

Promise.all = async ps => {
    const results = [];
    for await (const p of ps) {
        results.push(p);
    }
    return results;
};
 

Great post Jason! Just have a quick question, in your recursive method using promise, the order will be not be random if I understand it correctly?

 

No. The result would not be in random order. It should be in the order of the promises.

 

In each recursive call, we wait until head is resolved and then we move on to the remaining promises, is that correct? If so, is that how promise.all should work?

You are correct. But the other asynchronous executions will not be blocked.

If so, is that how promise.all should work?

I guess this depends on the implementation. I am not so sure how different browsers do it as they are implementation details that I don't really need to care.

code of conduct - report abuse