You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Async与多Await调用:调用栈挂起及Promise执行时序疑问

Promise并行执行与async/await的执行逻辑误区解析

问题描述

在使用Promise和async函数时,我了解到async函数内部遇到await时,JS引擎会挂起当前调用栈的函数调用,等待被await的Promise resolve。但运行以下代码后发现结果和预期不符:

const pr = new Promise((res, rej) => {
  setTimeout(() => {
    res("promise Execution done")
  }, 5000);
});

const pr2 = new Promise((res, rej) => {
  setTimeout(() => {
    res("promise Execution done222222")
  }, 10000);
});

async function handelPr() {
  const val1 = await pr;
  console.log("Hello");
  console.log(val1);

  const val2 = await pr2;
  console.log("Hello-->");
  console.log(val2);
}
handelPr()

实际运行总耗时10秒:pr在5秒后resolve,pr2再过5秒后resolve。但我预期pr resolve后pr2才开始执行,总耗时应为15秒;若将pr的延时改为10秒、pr2改为5秒,总耗时仍为10秒。请问这些Promise是否在并行执行?还是我对事件循环的理解存在误区?


问题解答

你的核心误区在于Promise的执行时机:当你通过new Promise()创建实例时,传入的executor函数(即(res, rej) => {...}的回调)会立即同步执行,并非等到await时才启动内部的异步操作。

具体执行流程拆解

  1. 脚本一开始运行,pr和pr2的Promise实例就被创建了:

    • pr内部的setTimeout立刻开始计时(5秒后触发resolve)
    • pr2内部的setTimeout也立刻开始计时(10秒后触发resolve)
      这两个定时器是同时启动的,和后续的handelPr调用、await逻辑完全无关。
  2. 调用handelPr后的执行:

    • 第一个await pr等待5秒,此时pr2的定时器已经运行了5秒,剩余5秒就会resolve,所以总耗时等于pr2的定时器时长10秒。
    • 如果把pr的延时改为10秒、pr2改为5秒,pr2的定时器在第5秒就已经resolve了,但await pr需要等10秒,等prresolve后,await pr2会直接拿到已resolve的结果,所以总耗时还是10秒。

如何实现预期的串行执行?

要让pr2在prresolve后才启动,需要把pr2的创建放到await pr之后,这样它的executor函数才会在prresolve后才执行,内部的定时器才会开始计时:

async function handelPr() {
  // 先创建pr并等待其resolve
  const pr = new Promise((res, rej) => {
    setTimeout(() => {
      res("promise Execution done")
    }, 5000);
  });
  const val1 = await pr;
  console.log("Hello");
  console.log(val1);

  // pr resolve后再创建pr2,启动其内部定时器
  const pr2 = new Promise((res, rej) => {
    setTimeout(() => {
      res("promise Execution done222222")
    }, 10000);
  });
  const val2 = await pr2;
  console.log("Hello-->");
  console.log(val2);
}
handelPr()

此时总耗时就是5秒+10秒=15秒,符合你最初的预期。

关键结论

  • Promise的executor函数是同步执行的,创建实例时就会触发内部的异步操作(比如setTimeout)。
  • await的作用只是暂停当前async函数的执行,等待已存在的Promise状态变更,不会控制Promise内部异步操作的启动时机。
  • 要实现异步操作的串行执行,需将后续Promise的创建放在前一个await之后。

内容的提问来源于stack exchange,提问作者Manthan Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:23:30