promise.all()
Prompt
Implement a function customPromiseAll that takes an array of promises and returns a new promise. It should behave like the native Promise.all() but you cannot use Promise.all in your implementation.
Playground
Your function should return a new Promise. Inside it,
loop through the input array with forEach and attach
.then() to each promise to collect its result when it
resolves.
Use Promise.resolve(promise) to wrap each item. This
handles non-promise values like numbers or strings by
turning them into promises that resolve immediately.
The results must be in the same order as the input, even
if promises resolve out of order. Use results[index] = value (not push) to place each result at the correct
position.
Keep a counter that increments in each .then(). When the
counter equals the array length, all promises are done and
you can resolve(results). For rejections, pass reject
directly to .catch() so the first failure immediately
rejects the outer promise.
Solution
Explanation
Promise.all takes a bunch of promises and waits for ALL of them to finish. If they all succeed, you get an array of all the results. If even one fails, the whole thing fails immediately with that error.
Think of it like ordering food for a group. Everyone orders something different. The waiter only brings the food to the table when ALL dishes are ready. But if the kitchen burns one dish, the whole order is cancelled.
How the solution works
We return a new Promise. Inside it, we loop through every promise in the input array and attach a .then() to each one. When a promise resolves, we store its value in a results array at the same index. We also bump a counter.
The critical insight is order preservation. Promises can resolve in any order. A slow network request might finish after a fast one. But Promise.all guarantees the results array matches the input order. That's why we use results[index] = value instead of results.push(value). Push would give us results in whatever order they happened to finish.
When the counter reaches the length of the input array, we know every promise has resolved, so we resolve the outer promise with the full results array.
If any promise rejects, we pass reject directly to .catch(). The first rejection immediately rejects the outer promise. Any promises that resolve after that are ignored because a promise can only settle once.
Why Promise.resolve(promise)?
You might wonder why we wrap each item in Promise.resolve(). It's because the input array might contain non-promise values like numbers or strings. Promise.resolve(42) turns 42 into a promise that immediately resolves with 42. If the value is already a promise, Promise.resolve() just returns it unchanged. This one line handles both cases.
The empty array edge case
If the input array is empty, we immediately resolve with an empty array. There's nothing to wait for. This matches the native Promise.all([]) behavior.