Mark As Completed Discussion

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:

JAVASCRIPT
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.

Question

Try to solve this here or in Interactive Mode.

How do I practice this challenge?

JAVASCRIPT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

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.

JAVASCRIPT
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.

JAVASCRIPT
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.

JAVASCRIPT
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.

JAVASCRIPT
1let pending = promises.length;

Step 5: Iterating Through the Promises

We'll iterate through the promises, resolving each one.

JAVASCRIPT
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.

JAVASCRIPT
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.

JAVASCRIPT
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.

JAVASCRIPT
1pending--;
2if (pending === 0) {
3  resolve(results);
4}

Final Code

Putting it all together, our final implementation looks like this:

JAVASCRIPT
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 a Promise 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.

JAVASCRIPT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

Alright, well done! Try another walk-through.

If you had any problems with this tutorial, check out the main forum thread here.