推荐答案
// www.javascriptcn.com code example
Promise.myAll = function(promises) {
return new Promise((resolve, reject) => {
if (!promises || promises.length === 0) {
resolve([]);
return;
}
const results = [];
let resolvedCount = 0;
const totalPromises = promises.length;
for (let i = 0; i < totalPromises; i++) {
Promise.resolve(promises[i]).then(value => {
results[i] = value;
resolvedCount++;
if (resolvedCount === totalPromises) {
resolve(results);
}
}, reason => {
reject(reason);
});
}
});
};本题详细解读
核心概念
Promise.all 的核心在于并发处理多个 Promise,并在所有 Promise 都成功 resolve 时返回一个包含所有结果的 Promise。如果其中任何一个 Promise 失败 reject,则 Promise.all 返回的 Promise 也会立即 reject。
实现步骤
- 接收参数:
Promise.myAll接收一个 Promise 数组promises作为参数。 - 返回 Promise: 返回一个新的 Promise,该 Promise 的状态将根据所有输入 Promise 的状态而定。
- 空数组处理: 如果
promises为空或不存在,则立即resolve一个空数组。 - 初始化: 初始化一个用于存储所有
resolve结果的results数组,以及一个计数器resolvedCount来记录已resolve的 Promise 数量。 - 遍历 Promise 数组: 遍历
promises数组。- 使用
Promise.resolve包装每个数组元素,确保即使元素不是 Promise ,也能统一处理。 - 对每一个 Promise 调用
.then方法 - 在
.then的resolve回调中:- 将
resolve的值按顺序存储到results数组的相应位置。 resolvedCount加一。- 检查
resolvedCount是否等于totalPromises,如果是,则说明所有 Promise 都resolve了,调用外部 Promise 的resolve并传入results数组。
- 将
- 在
.then的reject回调中:- 调用外部 Promise 的
reject,并将reject的原因传递出去。
- 调用外部 Promise 的
- 使用
- 错误处理: 如果任何一个 Promise 失败 (
reject),则立即reject整个Promise.all返回的 Promise,并传递reject的原因。
关键点
- 并发处理:
Promise.all需要并发处理所有的 Promise,而不是顺序处理,所以不能使用async await。 - 顺序返回: 返回的数组顺序需要和传入的顺序保持一致。
- 短路效应: 只要有一个 Promise
reject,整个Promise.all都会reject,这就是短路效应。 - 非 Promise 值处理: 输入的
promises数组中可能包含非 Promise 的值,所以需要使用Promise.resolve包装,将其转换为 Promise。 - 空数组处理: 当
promises为空时,应该立即resolve一个空数组。 - 错误处理: 需要正确捕获并传递 Promise 的错误。