promise.allSettled()
Prompt
Implement a function customPromiseAllSettled that takes an array of promises and returns a new promise. It should behave like the native Promise.allSettled() but you cannot use Promise.allSettled in your implementation.
Playground
Unlike Promise.all, this function never rejects. It
always resolves with an array of result objects. Both
successes and failures are collected. So your outer
promise only needs resolve, no reject.
For each promise, use .then() to create { status: 'fulfilled', value: ... } and .catch() to create { status: 'rejected', reason: ... }. Store these objects in a results array at the matching index.
You need a counter to know when ALL promises have settled
(regardless of whether they fulfilled or rejected). The
.finally() method runs after both .then() and
.catch(), so it's the perfect place to increment the
counter and check if (count === promises.length) resolve(results).
Solution
Explanation
Promise.allSettled is the most forgiving of all the Promise combinators. It never rejects. It waits for every single promise to finish (whether they succeed or fail), then gives you a report card for each one.
Promise.all is like a strict teacher: one failure and the whole class fails. Promise.allSettled is the teacher who says "let's see how everyone did" and gives you the full picture.
How the solution works
The structure is similar to Promise.all, but with two important differences:
-
The outer promise never rejects. Notice we only use
resolve, neverreject. There's no.catch(reject)on the outer promise. -
Both successes and failures are recorded as results. Instead of just storing the value, we create an object with a
statusfield:
// Success
{ status: 'fulfilled', value: 1 }
// Failure
{ status: 'rejected', reason: 'Error' }The .then() handler creates a fulfilled result. The .catch() handler creates a rejected result. The .finally() handler runs after either one and increments our counter. When the counter equals the array length, every promise has settled and we resolve with the full results array.
Why use .finally()?
We need to increment the counter regardless of whether a promise fulfilled or rejected. Without .finally(), we'd have to duplicate the counter logic in both .then() and .catch():
// Without finally (duplicate logic)
.then((value) => {
results[index] = { status: 'fulfilled', value };
settledCount++;
if (settledCount === promises.length) resolve(results);
})
.catch((reason) => {
results[index] = { status: 'rejected', reason };
settledCount++;
if (settledCount === promises.length) resolve(results);
}).finally() eliminates that duplication. It runs after the promise settles no matter the outcome, which is the perfect place for "I'm done, am I the last one?" logic.
When would you use Promise.allSettled?
It's great when you want to fire multiple independent requests and you don't want one failure to throw away all the results. For example, loading a dashboard where each widget fetches data independently. If one API is down, you still want to show the widgets that loaded successfully.