因为我不能在顶层运行 await,我必须把它放到一个异步函数中——为什么我可以直接调用那个异步函数?

响尾蛇

我有一个简短的 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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档