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

为何获取async函数返回的Promise结果必须使用await

现象复现代码
const delay = ms => new Promise(res => setTimeout(res, ms));

async function notInstant() {
  await delay(1);
  return 1;
}

(async function() {
 let a = notInstant();
 console.log(a);
 await delay(10000);
 console.log("Still a promise after 10 seconds even though the function only waits for 1 millisecond =>", a);
 a = await a;
 console.log("Printing directly after but now is resolved with the correct value", a);
})();
底层原理解释

出现这个反直觉的现象,本质是对两个JS核心规则理解有偏差:

  • 所有async函数的返回值固定是Promise对象
    执行let a = notInstant()时,a里存储的从一开始就是一个Promise实例的引用,赋值完成后这个引用不会自动发生变化。哪怕这个Promise在1ms后就从pending状态变为fulfilled、内部已经存好了resolve值1,它本身依然是Promise类型的对象,不会凭空转换成数字1。
    你等待10秒后打印a,输出的还是最开始存在变量里的Promise引用,自然看到的是Promise对象——只不过这时候这个Promise早就完成了状态落定,只是你没有主动把内部存储的值取出来而已。
  • await的核心作用是提取Promise的落定值,而非触发Promise执行
    不少人对await的误解是"加了await才会等待Promise执行完成",实际上在你调用notInstant()的那一刻,函数内部的逻辑就已经开始执行了,完全不需要等你写await才启动。
    await真正的运行逻辑是:暂停当前async函数的执行,让出事件循环线程,等后面跟随的Promise状态落定后,把Promise内部存储的resolve(或reject)值取出来,作为整个await表达式的返回值。
    你执行a = await a时,a指向的那个Promise早在近10秒前就已经resolve完成,所以这里不会产生任何额外等待,会直接把内部存的值1取出来重新赋值给a。这时候变量a存储的内容才从原来的Promise引用变成了数字1,打印自然能看到正确结果。

关键误区:Promise状态从pending变为fulfilled/rejected时,只会修改自身内部的状态和值属性,不会自动替换掉变量里存储的对象引用。你不主动通过.then()回调或者await把内部值提取出来,变量里永远存的是Promise对象,和它有没有resolve、resolve了多久没有任何关系。

打个通俗的比方:你点了份外卖,骑手10分钟就把餐送到你家门口挂着了(对应Promise在1ms后完成resolve,值已经存在Promise对象内部),你在家打了10小时游戏没开门取餐(对应10秒内没有对a做任何取值操作),外卖不会自己拆开跑到你餐桌上。等你开门把外卖拿进来拆开(对应执行await a),你才能拿到里面的餐食,这时候你桌上放的才是能直接吃的饭,不是外面的外卖包装盒。

内容的提问来源于stack exchange,提问作者Sante Kyaku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:24:13