Promise.allSettled 手写需:1. 对每个输入用 Promise.resolve(p).then(...).catch(...) 统一包装并捕获终态;2. 预分配数组按索引写入结果以保序;3. 计数器达长度时 resolve 结果数组;4. 支持空数组、非 Promise 值及同步错误。

要手写 Promise.allSettled,核心是:对每个输入 Promise 单独调用 .then() 和 .catch()(或统一用 .finally() 配合状态标记),确保无论成功或失败都收集结果,并保持原始顺序。
1. 每个 Promise 必须独立捕获终态
不能直接用 await 或链式 .then().catch() 后再返回,否则某个 Promise 抛错会中断后续处理。必须为每个 Promise 单独设置“兜底”逻辑:
- 用
Promise.resolve(p).then(v => {...}).catch(e => {...})将成功/失败都转为确定结构的对象 - 或用
Promise.resolve(p).then(v => ({ status: 'fulfilled', value: v }), e => ({ status: 'rejected', reason: e })) - 注意:必须用
Promise.resolve()包一层,兼容非 Promise 值(如普通数字、字符串)
2. 结果必须按输入顺序排列
异步执行天然无序,不能靠 push 简单累积。正确做法是预分配数组,用索引定位:
- 初始化一个长度等于输入数组的空数组(
results = new Array(promises.length)) - 遍历输入时,把每个 Promise 的处理结果写入
results[i]对应位置 - 即使第 5 个 Promise 先完成,也只填到
results[4],不打乱顺序
3. 返回一个新 Promise,等全部“落地”才 resolve
需要计数器判断是否所有 Promise 都已 settled:
立即学习“Java免费学习笔记(深入)”;
- 声明
count = 0,每次处理完一个 Promise 就count++ - 当
count === promises.length时,调用resolve(results) - 无需 reject 分支——
allSettled永远不会 reject,哪怕所有输入都失败
4. 处理边界情况
健壮实现需覆盖这些点:
- 空数组:立即 resolve([])
-
非 Promise 值:用
Promise.resolve(x)统一包装 -
同步抛错:例如
Promise.reject(1)或throw new Error(),会被catch捕获 -
this 绑定:手写函数应能被任意上下文调用,避免依赖
this


















