← Daily Logs
BFE.dev 70

Implement Promise.allSettled

MediumJun 30, 2026promiseasyncpolyfill

Like Promise.all, but it never short-circuits — it waits for every input to settle and reports each outcome as a tagged `{ status, value }` or `{ status, reason }` object.

The problem

Reimplement `Promise.allSettled()`. It takes an iterable of values — promises or plain values — and returns a promise that resolves once every input has settled, never rejecting.

Each slot in the resolved array describes its input's outcome: `{ status: 'fulfilled', value }` when it resolved, or `{ status: 'rejected', reason }` when it rejected. Unlike Promise.all, one rejection doesn't sink the whole thing — every result is collected.

The approach

Same skeleton as my Promise.all: a pre-sized `result` array written by index to keep output order, plus a counter so I know when everything has settled. The difference is the combined promise only ever resolves — there's no path that rejects.

For each input I wrap it in `Promise.resolve()`, then `.then` records `{ status: 'fulfilled', value }` and `.catch` records `{ status: 'rejected', reason }`. Both bump the counter, so I lean on `.finally()` to do the 'are we done yet?' check in one place rather than duplicating it across the two paths. When the count hits the length, I resolve. I also guard the empty-array case up front so it resolves with `[]` instead of hanging.

The solution

js
/**
 * @param {Array<any>} promises - notice that input might contains non-promises
 * @return {Promise<Array<{status: 'fulfilled', value: any} | {status: 'rejected', reason: any}>>}
 */
function allSettled(promises) {
    // your code here
    return new Promise((resolve, reject) => {
      if(!promises.length) resolve([])
      let result = Array(promises.length).fill(null)
      let resolvedCount = 0
      for(let i=0;i<promises.length;i++) {
        Promise.resolve(promises[i]).then((val) => {
            resolvedCount++
            result[i] = {status:'fulfilled', value: val}
        }).catch((e) => {
          resolvedCount++
          result[i] = {status:'rejected', reason: e}
        }).finally(() => {
          if(resolvedCount == promises.length) {
            resolve(result)
          }
        })
      }
    })
}

Time O(n)Space O(n)

All entries