Good evening! Here's our prompt for today.
According to the MDN docs, the Promise.all() method "takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises". It is useful when there is a collection of promises that you need to resolve prior to some other code execution work that neeeds to be done.
Here's an example of it being used:
1const promise1 = Promise.resolve(5);
2const promise2 = 2022;
3const promise3 = new Promise((resolve, reject) => {
4 setTimeout(() => {
5 resolve("foo");
6 }, 100);
7});
8
9Promise.all([p1, p2, p3]).then((values) => {
10 console.log(values);
11 // will print [5, 2022, "foo"]
12});
One caveat to note is that it will reject if any of the input promises are rejected. It will reject with the first rejection message or error. This is different than Promise.allSettled
. The allSettled
sibling method waits for its input promises to all complete and returns the final result of each.

Try to solve this here or in Interactive Mode.
How do I practice this challenge?
xxxxxxxxxx
Promise.all = (promises) => {
return new Promise((resolve, reject) => {
const results = []; // Array to store the results of the promises
// TODO: Check if the promises array is empty, and if so, resolve with the empty results array
let pending = promises.length; // Counter for the number of pending promises
promises.forEach((promise, idx) => {
// TODO: Resolve each promise and store its result in the results array
// If all promises are resolved, call resolve with the results array
// If any promise is rejected, call reject
});
});
};
Here's how we would solve this problem...
How do I use this guide?
Solution
Starting the Function
Step 1: Creating the Structure
We begin by defining our function and returning a new promise. This sets the stage for handling multiple promises.
1Promise.all = (promises) => {
2 return new Promise((resolve, reject) => {
3 // This is where the magic happens!
4 });
5};
Handling Edge Cases
Step 2: Setting up the Results Array
Before we do anything else, we create an empty array to hold our results.
1const results = [];
Step 3: No Promises Edge Case
If there are no promises in the input array, we immediately resolve to the empty results array.
1if (!promises.length) {
2 resolve(results);
3 return;
4}
Resolving the Promises
Step 4: Tracking Pending Promises
We'll set up a counter to keep track of the pending promises. This helps us know when all promises are resolved.
1let pending = promises.length;
Step 5: Iterating Through the Promises
We'll iterate through the promises, resolving each one.
1promises.forEach((promise, idx) => {
2 // We'll be resolving each promise here
3});
Step 6: Resolving Each Promise
Inside our loop, we call Promise.resolve
on each promise. This takes care of converting non-promise values to promises.
1Promise.resolve(promise).then((value) => {
2 // We'll handle the resolved value here
3}, reject);
Step 7: Adding Values to Results
When a promise is resolved, we add its value to the results array at the corresponding index. This ensures the order of the results matches the input promises.
1results[idx] = value;
Step 8: Checking for Completion
We decrement our pending counter and check if it has reached zero. If so, we know all promises are resolved, and we can resolve our main promise with the results array.
1pending--;
2if (pending === 0) {
3 resolve(results);
4}
Final Code
Putting it all together, our final implementation looks like this:
1Promise.all = (promises) => {
2 return new Promise((resolve, reject) => {
3 const results = [];
4 if (!promises.length) {
5 resolve(results);
6 return;
7 }
8 let pending = promises.length;
9 promises.forEach((promise, idx) => {
10 Promise.resolve(promise).then((value) => {
11 results[idx] = value;
12 pending--;
13 if (pending === 0) {
14 resolve(results);
15 }
16 }, reject);
17 });
18 });
19};
This step-by-step breakdown of the Promise.all
implementation allows us to appreciate the intricacy of asynchronous programming. By understanding how to build such a method ourselves, we gain valuable insight into the nature of promises and how they are handled in JavaScript.
One Pager Cheat Sheet
Promise.all()
is used to take an iterable of promises as an input, wait for them to resolve, and return a single Promise that resolves to an array of the results,but will reject with the first rejection message or error
if any of the input promises are rejected.- We can implement an
all
function that takes an array of promises and returns aPromise
that resolves to an array of return values from the input.
This is our final solution.
To visualize the solution and step through the below code, click Visualize the Solution on the right-side menu or the VISUALIZE button in Interactive Mode.
xxxxxxxxxx
Promise.all = (promises) => {
return new Promise((resolve, reject) => {
const results = [];
if (!promises.length) {
resolve(results);
return;
}
let pending = promises.length;
promises.forEach((promise, idx) => {
Promise.resolve(promise).then((value) => {
results[idx] = value;
pending--;
if (pending === 0) {
resolve(results);
}
}, reject);
});
});
};
Alright, well done! Try another walk-through.
If you had any problems with this tutorial, check out the main forum thread here.