Implementing Promise.allSettled() from Scratch

Implementing Promise.allSettled() from Scratch

·

2 min read

The Promise.allSettled() method has become a valuable addition to the JavaScript language, providing a way to handle multiple promises and obtain their outcomes, whether they are fulfilled or rejected. Unlike Promise.all(), which rejects immediately if any of the promises are rejected, Promise.allSettled() waits for all promises to settle, providing a comprehensive summary of their results.

Let's delve into how you can implement your own allSettled() function using JavaScript.

Understanding Promise.allSettled()

Before we jump into the implementation, let's have a brief overview of Promise.allSettled().

The official definition from MDN states that Promise.allSettled() returns a promise that resolves after all the given promises have either been fulfilled or rejected. The result is an array of objects, each describing the outcome of a corresponding promise.

Now, let's implement this behavior from scratch using the provided code:

function allSettled(promises) {
  if (promises.length === 0) {
    return Promise.resolve([]);
  }

  const results = [];
  let completed = 0;

  return new Promise((resolve) => {
    for (let i = 0; i < promises.length; i++) {
      Promise.resolve(promises[i])
        .then((value) => {
          results[i] = { status: 'fulfilled', value };
        })
        .catch((reason) => {
          results[i] = { status: 'rejected', reason };
        })
        .finally(() => {
          completed++;
          if (completed === promises.length) {
            resolve(results);
          }
        });
    }
  });
}

Breaking Down the Implementation

Let's break down the code and understand how it mimics the behavior of Promise.allSettled().

  1. Initial Check: The function starts by checking if the input array of promises is empty. If so, it immediately resolves with an empty array, as there are no promises to settle.

  2. Processing Promises: The function then iterates through each promise in the input array. For each promise, it uses Promise.resolve() to handle both resolved values and non-promise values uniformly.

  3. Handling Fulfillment and Rejection: The then and catch blocks are responsible for handling fulfillment and rejection, respectively. The results are stored in an array with an object containing the status ('fulfilled' or 'rejected') and the corresponding value or reason.

  4. Final Resolution: The finally block keeps track of the number of completed promises. Once all promises are processed, the function resolves with the array containing the outcome of each promise.

Example Usage

Now, let's see how you can use this custom allSettled() function:

const promises = [
  Promise.resolve('Success'),
  Promise.reject('Error'),
  Promise.resolve('Another Success'),
];

allSettled(promises)
  .then((results) => {
    console.log(results);
  })
  .catch((error) => {
    console.error(error);
});

//OUTPUT:
/*
[
  { status: 'fulfilled', value: 'Success' },
  { status: 'rejected', reason: 'Error' },
  { status: 'fulfilled', value: 'Another Success' }
]
*/

This example will output an array containing the outcomes of each promise, including both fulfilled and rejected promises.

Did you find this article valuable?

Support Md Talha by becoming a sponsor. Any amount is appreciated!