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:
Promise.resolve(promise)â Handles non-Promise values (numbers, strings pass through)results[index]â Preserves order (even though promises resolve out of order)remainingcounter â Tracks completion without relying on array length- Empty array edge case â Resolves immediately with
[] - 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.