FossilsðŸ’ŧ CodingImplement Promise.all
ðŸĶ–DinosaurJavaScriptAsyncPromises

Implement Promise.all

This tests your understanding of Promise mechanics, concurrency, and edge cases. The senior answer handles non-promises, empty arrays, and fail-fast behavior.

Implement Promise.all

Interview Question: "Implement Promise.all from scratch."

The Implementation

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let remaining = promises.length;
 
    if (remaining === 0) {
      resolve(results);
      return;
    }
 
    promises.forEach((promise, index) => {
      Promise.resolve(promise).then(
        (value) => {
          results[index] = value;
          remaining--;
          if (remaining === 0) resolve(results);
        },
        (reason) => {
          reject(reason);
        }
      );
    });
  });
}

Key points to articulate:

  1. Promise.resolve(promise) — Handles non-Promise values (numbers, strings pass through)
  2. results[index] — Preserves order (even though promises resolve out of order)
  3. remaining counter — Tracks completion without relying on array length
  4. Empty array edge case — Resolves immediately with []
  5. Fail-fast — First rejection rejects the whole thing

Follow-Up: "Implement Promise.allSettled"

function promiseAllSettled(promises) {
  return new Promise((resolve) => {
    const results = [];
    let remaining = promises.length;
 
    if (remaining === 0) {
      resolve(results);
      return;
    }
 
    promises.forEach((promise, index) => {
      Promise.resolve(promise).then(
        (value) => {
          results[index] = { status: 'fulfilled', value };
          if (--remaining === 0) resolve(results);
        },
        (reason) => {
          results[index] = { status: 'rejected', reason };
          if (--remaining === 0) resolve(results);
        }
      );
    });
  });
}

Key difference: Never rejects. Both success and failure are captured in the results.

Follow-Up: "Implement Promise.race"

function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      Promise.resolve(promise).then(resolve, reject);
    });
  });
}

First to settle wins. The Promise constructor ignores subsequent resolve/reject calls.