JavaScript Promise.all:并发执行、结果顺序与失败处理
Promise.all 用来等待一组任务全部成功,并按输入顺序返回结果。它不会把普通函数自动执行,也不会在一个任务失败后自动取消其他任务。能否并发取决于任务何时启动,以及这些任务是否彼此独立。
先启动独立任务,再一起等待
const assert = require('node:assert/strict');
const delay = (label, ms) => new Promise(resolve =>
setTimeout(() => resolve(label), ms));
(async () => {
const jobs = [delay('slow', 30), delay('fast', 5)];
const result = await Promise.all(jobs);
assert.deepEqual(result, ['slow', 'fast']);
console.log(JSON.stringify(result));
})();
预期输出 ["slow","fast"]。两个 delay 调用创建任务后,Promise.all 等待它们;结果不会因为 fast 先完成而颠倒。这里的时间只是演示任务顺序,不是性能基准。
把任务启动和结果等待分开看
调用 delay 会立即创建 Promise 并安排定时回调,构造 jobs 数组时两个调用已经发生。随后 Promise.all 只负责组织这些 Promise 的完成结果。它不是把普通函数变成任务的执行器,也不会因为你传入一个函数列表就自动逐项调用函数。
如果先 await 第一个请求,拿到结果后才发起第二个请求,那么请求阶段已经按顺序执行。最后再将结果放进 Promise.all,并不能把先前的等待时间消除。真正能够重叠执行的前提,是这些任务彼此独立,并且在共同等待之前就已经启动。
失败聚合不等于取消执行
const assert = require('node:assert/strict');
(async () => {
let completed = false;
const other = new Promise(resolve => setTimeout(() => {
completed = true; resolve('done');
}, 15));
try { await Promise.all([Promise.reject(new Error('bad')), other]); }
catch (error) { console.log(error.message); }
await other;
assert.equal(completed, true);
console.log('other completed:', completed);
})();
预期打印 bad 和 other completed: true。若需要取消网络请求,应使用支持取消的请求接口和信号,单靠 Promise.all 不会停止已经启动的工作。

结果顺序不等于任务完成顺序
本例用两个不同的延迟制造完成先后,但结果数组的位置对应输入位置。slow 放在 jobs 的第一项,所以无论 fast 是否先完成,结果的第一项仍是 slow。实际请求中,这有利于把返回结果与预先定义的任务一一对应。
定时器的毫秒参数不是性能保证。事件循环忙碌时,回调可能更晚执行。因此示例通过结果内容验证行为,没有把某一次实测耗时当成 Promise.all 的固定开销。评估真实提速时,应统计完整请求、失败处理和后续加工的总耗时。
根据依赖关系和规模决定并发
- 前一任务的结果决定后一任务参数:保持顺序,不应强行并发。
- 需要收集成功和失败的全部结果:考虑 Promise.allSettled。
- 大量任务:使用有并发上限的调度,避免一次启动所有网络请求。
不要先逐个 await 得到结果后,再把结果放入 Promise.all;那时耗时操作已经顺序完成,无法补回并发收益。
一个任务失败后,还要处理其他工作的去向
聚合 Promise 拒绝时,调用方可以立即进入 catch,但已经启动的其他任务仍可能继续运行。示例在捕获 bad 后再等待 other,最终打印 completed 为 true,用来明确区分“等待组合已经失败”和“所有工作已经停止”。
如果你需要展示全部请求各自的成功或失败情况,可以考虑 Promise.allSettled,再逐项处理结果。若业务要求一处失败就停止其他网络请求,则需要任务本身支持取消,并由调用方发出取消信号。不要把取消当作 Promise.all 自带的行为。
生产环境还应限制并发规模。一次给成千上万个请求创建 Promise,可能让目标服务或本地连接资源承受过高压力。先明确最大在途数量、超时和重试条件,再选择调度方式。存在前后依赖的任务继续顺序执行,独立任务才适合放入同一个并发组。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









