为何async/await与Promise.all执行耗时相同?
为什么依次await三个2秒Promise总耗时不是6秒?以及与Promise.all的区别
我创建了三个包含2000ms setTimeout的Promise,通过async/await依次等待它们,原本预期总耗时为6000毫秒:
let PromiseOne = new Promise(resolve => { setTimeout(() => { resolve('Promise One'); }, 2000); }); let PromiseTwo = new Promise(resolve => { setTimeout(() => { resolve('Promise Two'); }, 2000); }); let PromiseThree = new Promise(resolve => { setTimeout(() => { resolve('Promise Three'); }, 2000); }); (async() => { console.time(); let ResponseOne = await PromiseOne; let ResponseTwo = await PromiseTwo; let ResponseThree = await PromiseThree; console.log(ResponseOne, ResponseTwo, ResponseThree); console.timeEnd(); })();
但实际控制台输出显示总耗时仅约2.004秒,与预期不符。原本认为每个await会占用2000毫秒的执行时间,但实际并非如此。请问上述使用async/await的写法与下方使用Promise.all的写法有何区别?
let PromiseOne = new Promise(resolve => { setTimeout(() => { resolve('Promise One'); }, 2000); }); let PromiseTwo = new Promise(resolve => { setTimeout(() => { resolve('Promise Two'); }, 2000); }); let PromiseThree = new Promise(resolve => { setTimeout(() => { resolve('Promise Three'); }, 2000); }); (() => { Promise.all([PromiseOne, PromiseTwo, PromiseThree]).then(res => { console.log(res); }); })();
先解释为什么总耗时不是6秒
核心原因是:Promise在被实例化的那一刻就开始执行了,不是等到await的时候才启动。
你代码里的三个PromiseOne、PromiseTwo、PromiseThree在脚本一开始就被创建了,它们内部的setTimeout会同时开始计时,2秒后三个Promise会几乎同时完成。后面的await只是按顺序等待每个Promise的结果,但它们的执行过程是并行的,所以总耗时接近2秒,而不是3个2秒相加的6秒。
如果要让三个Promise串行执行(总耗时6秒),你需要在await第一个Promise完成后,再创建第二个Promise:
(async() => { console.time(); // 第一个Promise执行完成后,才创建第二个 let ResponseOne = await new Promise(resolve => setTimeout(() => resolve('Promise One'), 2000)); let ResponseTwo = await new Promise(resolve => setTimeout(() => resolve('Promise Two'), 2000)); let ResponseThree = await new Promise(resolve => setTimeout(() => resolve('Promise Three'), 2000)); console.log(ResponseOne, ResponseTwo, ResponseThree); console.timeEnd(); // 此时总耗时约6秒 })();
两种写法的区别
在你给出的代码场景中,两种写法的执行效率是一致的(总耗时都是约2秒),因为三个Promise都是并行启动的。它们的主要区别体现在以下几点:
1. 结果获取方式
- 你的
async/await写法:按顺序逐个获取单个Promise的结果,每个await返回对应Promise的resolve值,变量ResponseOne、ResponseTwo、ResponseThree分别对应三个结果。 Promise.all写法:等待所有Promise完成后,一次性返回一个包含所有结果的数组,需要从数组中提取对应的值(比如res[0]是第一个Promise的结果)。
2. 错误处理逻辑
- 你的
async/await写法:如果某个Promise reject,后续的await语句会停止执行,代码会直接进入catch块(如果有)。比如如果PromiseOnereject,ResponseTwo和ResponseThree的代码不会执行。 Promise.all写法:只要有一个Promise reject,Promise.all会立刻触发reject,忽略其他尚未完成的Promise的状态。
3. 代码结构灵活性
async/await写法更适合需要按顺序处理结果的场景(比如用前一个Promise的结果作为下一个的参数),代码可读性更强,更接近同步代码的逻辑。Promise.all写法更适合不需要依赖顺序、只需要等待所有任务完成的场景,代码更简洁,能一次性处理所有结果。
内容的提问来源于stack exchange,提问作者Junseong Park
相关产品推荐
相关产品推荐

