1. 核心思路
以下是该promiseAll
实现的核心思路梳理,采用分步式解析:
1.1 初始化阶段
- 创建容器 :
const result = []
预分配结果数组,用于存储每个Promise的解析值。 - 计数器 :
let completedCount = 0
必须用let
声明,用于统计已完成的Promise数量(原代码const
会导致无法递增)。
1.2. 边界处理
-
空数组检测 :
javascriptif (apis.length === 0) { resolve(result); return; // 立即终止执行 }
若输入为空数组,直接同步返回空结果数组(与原生
Promise.all
行为一致)。
1.3. 遍历处理每个Promise
-
统一包装 :
Promise.resolve(api)
通过Promise.resolve
强制将非Promise值(如数字、普通对象)转换为Promise,统一处理逻辑。 -
索引存储 :
result[index] = res
按原始顺序存储结果(原代码push
会导致结果顺序与输入顺序不一致)。 -
完成计数 :
javascriptcompletedCount++; if (completedCount === apis.length) { resolve(result); }
只有当完成数等于总Promise数时,才触发整体
resolve
。
1.4. 错误处理
- 短路机制 :
.catch(reject)
任一Promise失败时立即调用reject
,中断后续处理(符合Promise.all
的快速失败特性)。
2. 最终代码
js
/**
* 自定义实现Promise.all功能
* @param {Array} apis - Promise对象数组(支持非Promise值)
* @returns {Promise} 返回新Promise,全部成功时resolve结果数组,任一失败立即reject
*/
function promiseAll(apis = []) {
return new Promise((resolve, reject) => {
const result = [];
let completedCount = 0; // 必须用let声明(原代码const会导致无法递增)
// 空数组直接resolve
if (apis.length === 0) {
resolve(result);
return; // 需立即返回避免继续执行
}
apis.forEach((api, index) => {
// 用Promise.resolve包裹确保处理非Promise值
Promise.resolve(api)
.then((res) => {
// 按原始顺序存储结果(原代码用push会导致顺序错乱)
result[index] = res;
completedCount++;
// 全部完成时才resolve(原代码条件错误:count === result.length)
if (completedCount === apis.length) {
resolve(result);
}
})
.catch(reject); // 任一失败立即终止
});
});
}