Skip to content
Async · Core · about 20 minutes

Promise.all by hand

Implement promiseAll(values) without the Promise combinators (the tests make Promise.all, allSettled, race and any throw). It resolves with an array of results in input order once every item has resolved. It rejects as soon as one item rejects, with that error. Items that are not promises count as already resolved. An empty list resolves with [] at once. In the tests a task [30, a] resolves with a after 30 ms and [30, boom, true] rejects with Error(boom); an outcome is [status, value, time]. An item written {value: 1} is the plain value 1.

Start from

function promiseAll(values) {
  // Resolve with every result in input order, or reject on the first failure.
}

Hints

Each hint gives away a little more. Open one only when you need it.

  1. Hint 1

    Return a new Promise and count how many items are still open.

  2. Hint 2

    Store each result at its own index, not with push: items finish in any order.

  3. Hint 3

    Wrap each item in Promise.resolve so plain values work, and pass reject as the second argument of then.

Solution

From here on the page gives the method away. If you are still solving, go back to the hints.

JavaScript
function promiseAll(values) {
  return new Promise((resolve, reject) => {
    const results = [];
    let left = values.length;
    if (left === 0) return resolve(results);
    values.forEach((value, index) => {
      Promise.resolve(value).then((result) => {
        results[index] = result;
        if (--left === 0) resolve(results);
      }, reject);
    });
  });
}

What an interviewer looks for

It is the most asked promise exercise. The three things scored: results by index, the empty list, and rejecting once without waiting for the rest.