手写 Promise.all 是一个很好的练习,可以帮助理解 Promise 的内部实现和并发处理的逻辑。Promise.all 的作用是等待所有的 Promise 实例都完成(resolve 或 reject)后返回一个结果。如果所有的 Promise 都成功(resolve),则返回一个包含所有结果的数组;如果有任何一个 Promise 失败(reject),则立即返回失败的结果。
实现思路
- 初始化状态:创建一个新的
Promise实例。 - 收集结果:遍历传入的
promises数组,收集每个 Promise 的结果。 - 处理完成状态:当所有 Promise 都 resolve 时,返回一个包含所有结果的数组。
- 处理失败状态:如果有任何一个 Promise reject,则立即返回失败的结果。
代码实现
下面是一个完整的 Promise.all 的手写实现:
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
const results = []; // 存储每个 Promise 的结果
let completedCount = 0; // 记录已完成的 Promise 数量
// 遍历 promises 数组
promises.forEach((promise, index) => {
promise.then(
(result) => {
results[index] = result; // 存储结果
completedCount++; // 增加已完成的数量
// 如果所有 Promise 都已完成
if (completedCount === promises.length) {
resolve(results);
}
},
(error) => {
reject(error); // 有任何一个 Promise 失败,立即拒绝
}
);
});
});
}
// 测试代码
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
myPromiseAll([promise1, promise2, promise3])
.then((results) => {
console.log('All resolved:', results); // 输出: All resolved: [1, 2, 3]
})
.catch((error) => {
console.error('Error:', error);
});
const promise4 = Promise.reject(new Error('Failed'));
myPromiseAll([promise1, promise2, promise4])
.then((results) => {
console.log('All resolved:', results);
})
.catch((error) => {
console.error('Error:', error); // 输出: Error: Failed
});
解释
- 创建新的
Promise实例:myPromiseAll函数返回一个新的Promise实例。 - 收集结果:使用
results数组来存储每个 Promise 的结果。 - 计数器:
completedCount变量用于记录已完成的 Promise 数量。 - 处理完成状态:当所有 Promise 都 resolve 时,通过
resolve回调函数返回results数组。 - 处理失败状态:如果有任何一个 Promise reject,则通过
reject回调函数立即返回错误。
测试代码
上面的测试代码展示了如何使用 myPromiseAll 函数。当所有 Promise 都成功时,输出结果数组;如果有任何一个 Promise 失败,则输出错误信息。
总结
通过手写 Promise.all,我们可以更好地理解 Promise 的内部实现和并发处理的逻辑。这种方法不仅有助于学习 Promise 的基本概念,还能加深对并发编程的理解。在实际开发中,这种实现方式也能帮助我们更好地处理多个异步任务的并发执行。