Promise.all 实现
手写 Promise.all 方法
问题
从零实现 Promise.all 方法。
解答
function promiseAll(promises) {
return new Promise((resolve, reject) => {
// 处理非数组输入
const arr = Array.from(promises);
const results = [];
let completed = 0;
// 空数组直接返回
if (arr.length === 0) {
resolve(results);
return;
}
arr.forEach((promise, index) => {
// 用 Promise.resolve 包装,处理非 Promise 值
Promise.resolve(promise)
.then((value) => {
// 按原顺序存储结果
results[index] = value;
completed++;
// 全部完成后 resolve
if (completed === arr.length) {
resolve(results);
}
})
.catch((error) => {
// 任意一个失败就 reject
reject(error);
});
});
});
}
测试
// 测试1:全部成功
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise((resolve) => setTimeout(() => resolve(3), 100));
promiseAll([p1, p2, p3]).then(console.log); // [1, 2, 3]
// 测试2:包含非 Promise 值
promiseAll([1, 2, Promise.resolve(3)]).then(console.log); // [1, 2, 3]
// 测试3:有一个失败
const p4 = Promise.reject('error');
promiseAll([p1, p4, p3]).catch(console.log); // 'error'
// 测试4:空数组
promiseAll([]).then(console.log); // []
关键点
- 返回一个新的 Promise
- 用
Promise.resolve()包装每个元素,兼容非 Promise 值 - 结果数组要保持原顺序,用索引赋值而非 push
- 用计数器判断是否全部完成
- 任意一个 reject 就立即 reject 整体
目录