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.