Promise.any 全失败时必须抛出 AggregateError,其 errors 属性包含所有 rejection reason;需等待全部 Promise 结束,用计数器和错误数组实现,兼容旧环境需手动模拟 AggregateError。

<p>Promise.any 在所有 Promise 都 reject 时,必须抛出 <strong>AggregateError</strong>(而非普通 Error),且该错误的 <code>errors</code> 属性需包含所有被拒绝的 reason。</p> <h3>核心逻辑:收集全部 rejection,最后统一抛出 AggregateError</h3> <p>与 Promise.race 不同,Promise.any 要“等待至少一个成功”,但不能提前退出;它必须等所有 Promise 结束(fulfilled 或 rejected),才能判断是否全失败。关键点:</p>
- 用计数器跟踪已结束的 Promise 数量(
settledCount) - 用数组缓存所有 rejection 的 reason(
errors) - 一旦有任意一个 fulfilled,立即 resolve 对应 value
- 当所有 Promise 都 settled 且无 fulfilled → new AggregateError(errors)
注意 AggregateError 的兼容性与构造方式
原生 AggregateError 是 ES2021 特性,手写时需兼容旧环境:
- 若全局存在
AggregateError,直接使用:new AggregateError(errors, 'All promises were rejected') - 否则手动模拟:创建继承自 Error 的类,添加
errors属性和正确 name - 不要用
new Error(JSON.stringify(errors))—— 这不是标准 AggregateError,缺少 errors 属性和语义
完整可运行的手写实现
以下代码满足规范,包括错误类型、errors 属性、message 和堆栈行为:
function PromiseAny(promises) {
return new Promise((resolve, reject) => {
const values = [];
const errors = [];
let settledCount = 0;
const len = promises.length;
if (len === 0) {
reject(new AggregateError([], 'All promises were rejected'));
return;
}
for (let i = 0; i {
if (values.length === 0) resolve(value);
})
.catch(reason => {
errors.push(reason);
})
.finally(() => {
settledCount++;
if (settledCount === len && values.length === 0) {
const aggregateErr = typeof AggregateError === 'function'
? new AggregateError(errors, 'All promises were rejected')
: Object.assign(new Error('All promises were rejected'), {
name: 'AggregateError',
errors
});
reject(aggregateErr);
}
});
}
});
}
验证 AggregateError 是否符合要求
测试全失败场景,确保:
-
err instanceof AggregateError为 true -
err.errors是数组,长度等于输入 promise 个数 -
err.message包含提示信息(非必需但推荐) - 在支持环境里,
err.name === 'AggregateError'
例如:PromiseAny([Promise.reject(1), Promise.reject(2)]) 应抛出带有 errors: [1, 2] 的 AggregateError。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











