本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、Promise.all 的核心特性
1. 标准行为
// 输入:Promise数组
// 输出:新的Promise
Promise.all([promise1, promise2, ...])
.then(values => {
// 所有Promise成功时触发
// values按输入顺序排列的结果数组
})
.catch(reason => {
// 任意一个Promise失败时立即触发
});
2. 关键特性
| 特性 | 描述 |
|---|---|
| 全部成功 | 返回结果数组(保持原始顺序) |
| 快速失败 | 任一失败立即拒绝 |
| 非Promise值 | 直接作为结果返回 |
| 空输入 | 返回已解决的Promise |
二、手写实现示例
1. 基础实现
function myPromiseAll(promises) {
// 1. 返回新的Promise
return new Promise((resolve, reject) => {
// 2. 处理非数组输入
if (!Array.isArray(promises)) {
return reject(new TypeError('Arguments must be an array'));
}
const results = [];
let completedCount = 0;
const total = promises.length;
// 3. 处理空数组情况
if (total === 0) {
return resolve(results);
}
// 4. 遍历处理每个Promise
promises.forEach((promise, index) => {
// 5. 确保处理非Promise值(用Promise.resolve包装)
Promise.resolve(promise)
.then(value => {
// 6. 按顺序存储结果
results[index] = value;
completedCount++;
// 7. 检查是否全部完成
if (completedCount === total) {
resolve(results);
}
})
.catch(reason => {
// 8. 任一失败立即拒绝
reject(reason);
});
});
});
}
2. 增强版实现
function enhancedPromiseAll(promises, options = {}) {
return new Promise((resolve, reject) => {
/* 新增功能:
- 超时控制
- 进度回调
- 部分成功记录
*/
const {
timeout,
onProgress
} = options;
// ...(基础实现逻辑)
// 超时控制
if (timeout) {
const timer = setTimeout(() => {
reject(new Error(`Operation timed out after ${timeout}ms`));
}, timeout);
// 清理定时器
promises.finally(() => clearTimeout(timer));
}
// 进度回调
if (onProgress) {
promises.forEach(promise => {
promise.finally(() => {
completedCount++;
onProgress(completedCount / total);
});
});
}
});
}
三、实现原理图解

四、关键实现技巧
1. 顺序保持机制
// 使用索引而非push保证顺序
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(value => {
results[index] = value; // 关键点:按原始位置存储
// ...
});
});
2. 完成计数优化
// 原子性计数方案
let completedCount = 0;
function checkCompletion() {
// 使用闭包避免竞态条件
if (++completedCount === promises.length) {
resolve(results);
}
}
3. 非Promise处理
// 统一处理方案
Promise.resolve(item).then(...)
// 等价于:
if (item instanceof Promise) {
item.then(...)
} else {
Promise.resolve(item).then(...)
}
五、边界情况测试
测试用例集
// 1. 基础功能
myPromiseAll([
Promise.resolve(1),
Promise.resolve(2)
]).then(console.log); // [1, 2]
// 2. 快速失败
myPromiseAll([
Promise.resolve(1),
Promise.reject('error')
]).catch(console.log); // 'error'
// 3. 非Promise值
myPromiseAll([
1,
Promise.resolve(2)
]).then(console.log); // [1, 2]
// 4. 空数组
myPromiseAll([]).then(console.log); // []
// 5. 顺序保证
myPromiseAll([
new Promise(r => setTimeout(() => r(1), 100)),
Promise.resolve(2)
]).then(console.log); // [1, 2]
六、与原生实现的差异
| 特性 | 手写实现 | 原生实现 |
|---|---|---|
| 迭代器支持 | 仅数组 | 支持可迭代对象 |
| 微任务调度 | 简单实现 | 严格遵循规范 |
| 性能优化 | 基础 | 引擎级优化 |
| 错误类型 | 简单错误 | 特定错误类型 |
七、进阶实现建议
1. 支持可迭代对象
function iterablePromiseAll(iterable) {
// 将iterable转为数组
const promises = Array.from(iterable);
// ...其余逻辑相同
}
2. 取消功能扩展
function cancellablePromiseAll(promises) {
let isCancelled = false;
const wrapped = promises.map(p =>
p.catch(err => {
if (isCancelled) throw new Error('Cancelled');
throw err;
})
);
const result = myPromiseAll(wrapped);
result.cancel = () => {
isCancelled = true;
};
return result;
}
3. 性能优化版
function fastPromiseAll(promises) {
// 预分配数组
const results = new Array(promises.length);
let remaining = promises.length;
return new Promise((resolve, reject) => {
promises.forEach((promise, i) => {
Promise.resolve(promise).then(
value => {
results[i] = value;
if (--remaining === 0) resolve(results);
},
reject
);
});
});
}
八、实际应用示例
1. 并行请求合并
async function fetchUserData(userId) {
const [profile, orders, messages] = await myPromiseAll([
fetch(`/users/${userId}`),
fetch(`/orders?user=${userId}`),
fetch(`/messages/${userId}`)
]);
return { profile, orders, messages };
}
2. 批量文件操作
function batchReadFiles(files) {
return myPromiseAll(
files.map(file =>
new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
err ? reject(err) : resolve(data);
});
})
)
);
}
总结
- 核心逻辑:通过计数器和数组索引维护顺序
- 错误处理:任一失败立即终止
- 边界处理:空数组、非Promise值等特殊情况
- 性能考量:避免不必要的内存分配
鸿蒙中Promise.all()实现原理详解
1850

被折叠的 条评论
为什么被折叠?



