Implementing Promise.allSettled Polyfill

ยท

3 min read

Introduction:

JavaScript Promises have become a fundamental part of modern web development, allowing developers to write asynchronous code in a more readable and maintainable way. One of the recent additions to the Promise API is the Promise.allSettled method, which returns a promise that resolves after all of the given promises have either resolved or rejected, with an array of objects that each describes the outcome of each promise. In this blog post, we will explore how to polyfill Promise.allSettled for environments that do not yet support it, which can be a valuable skill for those preparing for technical interviews.

Understanding Promise.allSettled:

Before we dive into the polyfill implementation, let's first understand the behavior of Promise.allSettled. Unlike Promise.all, which short-circuits and rejects immediately if any of the input promises reject, Promise.allSettled waits for all promises to settle (either resolve or reject) and then returns a promise that resolves with an array of result objects. Each result object has a status property that indicates whether the promise was fulfilled ('fulfilled') or rejected ('rejected'), and a value or reason property containing the fulfillment value or rejection reason, respectively

Implementing the Polyfill:

  1. Check for Existing Implementation:

    • Before polyfilling, we check if Promise.allSettled already exists. If it does, we do not override it.
  2. Polyfill Definition:

    • We define Promise.allSettled as a function that takes an array of promises as its input.

    • It returns a new promise created by calling Promise.all.

    • Inside Promise.all, we map over each promise in the input array.

  3. Mapping Promises:

    • For each promise, we call .then to handle the fulfillment and rejection cases separately.

    • If the promise fulfills, we return an object with status: 'fulfilled' and value: <fulfillment value>.

    • If the promise rejects, we return an object with status: 'rejected' and reason: <rejection reason>.

  4. Returning Mapped Promises:

    • The map method returns an array of mapped promises (each mapping to a promise that resolves with an object describing its outcome).

    • This array of promises is passed to Promise.all, which waits for all promises to settle (either resolve or reject).

  5. Final Result:

    • The final result of Promise.allSettled is a promise that resolves with an array of result objects, where each object describes the outcome of the corresponding input promise.
if (!Promise.allSettled) {
    Promise.allSettled = function (promises) {
        return Promise.all(
            promises.map(promise =>
                promise.then(
                    value => ({
                        status: 'fulfilled',
                        value
                    }),
                    reason => ({
                        status: 'rejected',
                        reason
                    })
                )
            )
        );
    };
}

Test cases

Promise.allSettled([])
    .then(results => {
        console.log(results);
    });
// resolves []
const mixedPromises = [
    Promise.resolve('Fulfilled'),
    Promise.reject('Rejected'),
    Promise.resolve('Another Fulfilled'),
    Promise.reject('Another Rejected')
];

Promise.allSettled(mixedPromises)
    .then(results => {
        console.log(results);
    });

// output
/*
[
    { status: 'fulfilled', value: 'Fulfilled' },
    { status: 'rejected', reason: 'Rejected' },
    { status: 'fulfilled', value: 'Another Fulfilled' },
    { status: 'rejected', reason: 'Another Rejected' }
]
*/

Refrences

promise all settled mdn

ย