我有一个简短的 Node.js 脚本,我需要另一个包并从中调用异步函数,然后想要打印返回值。如果我只是await
从顶层返回值,那么我会得到一个错误,说我只能await
在异步函数本身内部使用。所以显然要走的路是这样的:
async function main() {
foo = await someOtherAsyncFunc();
console.log(foo);
}
main()
要么:
(async function() {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
要么:
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
(归功于聊天中的 VLAZ https://chat.stackoverflow.com/transcript/message/54186176#54186176)
这行得通 - 但我想进一步了解其背后的原因:我习惯于无法直接await
从顶层使用。但是,我也习惯于调用一些特殊的库函数来真正从顶层“冒险”进入异步。在 Python 中,请参见asyncio.run
示例。需要await
在异步函数内部有什么意义 - 如果我可以从顶层调用任何异步函数?那么为什么await
在顶层也不能使用呢?
顶级 await曾经不是一个东西,但现在在 ES6 模块中是可能的。
顶级 await 过去不是一个东西,并且仍然不是模块之外的东西的一个原因是它可能允许语法歧义。Async 和 await 是有效的变量名。模块之外。如果非模块脚本允许顶级等待,那么,如果不重新编写规范(并破坏向后兼容性),就会出现解析器无法确定特定实例是否是await
变量名的情况,或者被用作等待其右侧的 Promise 解决的语法。
为了避免任何歧义的可能性,解析器在解析一段代码时,本质上需要有标志来指示await
在任何给定点作为标识符是否有效,或者它是否作为异步语法有效,并且这两者绝不能相交。
模块脚本允许顶级等待(现在),因为在它们中一直禁止使用等待作为标识符,因此没有语法歧义。
相比之下,.then
在顶层使用的问题为零,因为它在任何情况下都不会导致任何歧义。
为什么它不只是返回一个永远不会执行的 Promise,因为它没有得到等待?
承诺并没有真正“执行”。它们可以被构建,或者等待完成,或者等待拒绝。如果您有一个 Promise,那么您已经有一些正在进行的代码(可能)最终会导致为 Promise 分配一个履行值。
悬挂 Promise 在语法上是允许的——解析为 Promises 但不与其他地方交互的值。(这是有道理的——每一个 .then
或.catch
产生一个新的 Promise。如果每一个 Promise 都必须被其他东西使用,你最终会得到无限的倒退。)
正在做
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
本质上是语法糖
someOtherAsyncFunc()
.then((foo) => {
console.log(foo);
});
没有必要在其中任何一个的末尾添加任何其他内容。(尽管建议在悬空的 Promise中添加 a .catch
,这样就不会发生未处理的拒绝)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句