await与then获取异步返回值差异:如何让.then结果可在下游访问
结论
不能直接在.then之后的同步代码里拿到异步返回结果,除非你让后续代码也等到.then的逻辑执行完成再运行,此时和直接使用await的效果完全一致。
原理说明
JS的事件循环机制决定了同步代码会优先执行完,再处理异步微任务(包括Promise的then/catch/finally回调)。你示例中console.log('baz returned: '+ z)属于同步代码,会在.then的赋值逻辑执行前就运行,所以z必然是undefined,和你用不用async函数没有关系。
如果非要用.then实现和await一样的效果,可以修改你的示例代码如下:
async function main (){ x = await foo(10); console.log('foo returned (after await): '+ x); y = await bar (10); console.log('bar returned (after await): '+ y); // .then链本身会返回一个新的Promise,我们可以await这个Promise await baz(10).then(result => { z = result; }); console.log('baz returned: '+ z); // 此时z已经赋值完成,能正常打印结果 }
这种写法和直接写z = await baz(10)逻辑完全等价,await本身就是Promise.then的语法糖,只是帮你省去了手动写回调的步骤。
针对你的实际场景的说明
你现在的Express初始化场景用await写是最优解。如果换成.then的写法,你需要把所有依赖schemaValidation、schemaDB的逻辑(包括mongoose.model定义、initAppRouter调用等)都放到.then的回调里,嵌套层级多了就会出现回调地狱,代码可读性和可维护性都会大幅下降。你当前的await写法已经是最简洁合理的实现。
补充注意点
- 所有
async函数的返回值都会自动包装成Promise,不管你有没有手动返回Promise对象 - 只要是异步操作的结果,不管用哪种方式接收,都不可能在未等待异步完成的同步代码里访问到
.then和await没有功能上的差异,只是写法不同,可根据场景自由选择
内容的提问来源于stack exchange,提问作者IMTanuki
相关产品推荐
相关产品推荐

