关于如何从异步函数通过Promise返回结果的困惑
关于如何从异步函数通过Promise返回结果的困惑
我太懂你这种困惑了!刚上手async/await的时候,很容易被它的“同步写法”迷惑,以为调用async函数就会直接拿到最终结果,但其实这里有个核心知识点你没get到,咱们一步步拆解:
问题出在哪?
首先记住这个铁律:所有async函数调用后,返回的永远是一个Promise对象,不管你函数里写了多少await。你看到的Got final result=[object Promise]就是这个原因——你直接把Promise对象转成字符串输出了,而不是它最终resolve的值。
再理一遍你的代码实际执行流程:
- 全局脚本调用
test2(),因为test2是async函数,它立刻返回一个未完成的Promise,同时开始执行test2内部的代码。 test2内部先打印Before promise,然后遇到await test1():这时候test2会暂停执行,把控制权交还给全局脚本(JavaScript是单线程的,不会因为await阻塞整个线程)。- 全局脚本继续往下走,执行
console.log("Got final result=" + final_result);,这时候final_result就是test2返回的那个未完成的Promise,所以打印出[object Promise]。 - 2秒后,
test1里的定时器触发,打印Timer fires,同时test1的Promise被resolve为Done,test2恢复执行:打印After promise、result=Done,最后test2返回的Promise也会被resolve为Done。
怎么改成你预期的结果?
要拿到test2的最终返回值,你需要等待它返回的Promise完成,有几种常用方法:
方法1:用async立即执行函数(IIFE)
这是浏览器里最通用的写法,不用额外配置:
<body> <script> // 用async立即执行函数包裹,就能在里面用await (async function() { let final_result = await test2(); console.log("Got final result=" + final_result); })(); </script> </body>
方法2:用Promise的.then()链式调用
既然test2返回的是Promise,直接用.then()处理结果:
<body> <script> test2().then(final_result => { console.log("Got final result=" + final_result); }); </script> </body>
方法3:顶层await(需配置模块环境)
如果你的页面支持ES模块(把script标签设为type="module"),可以直接用顶层await:
<body> <script type="module"> let final_result = await test2(); console.log("Got final result=" + final_result); </script> </body>
改完后的日志顺序
不管用哪种方法,最终的日志都会和你预期的一致:
Before promise Timer fires After promise result=Done Got final result=Done
最后再划个重点
await只能暂停当前async函数内部的执行,不会阻塞整个JavaScript线程——这是JavaScript异步非阻塞设计的核心。async/await只是让异步代码写起来像同步代码,但本质上还是基于Promise的异步操作,不会改变JavaScript单线程异步的本质哦。
备注:内容来源于stack exchange,提问作者c00000fd
相关产品推荐
相关产品推荐

