因为我不能 运行 在顶层等待,所以我必须将它放入异步函数中 - 为什么我可以直接调用该异步函数?
Because I can't run await on the top level, I have to put it into an async function - why can I then call that async function directly?
我有一个简短的 Node.js 脚本,我需要另一个包并从中调用一个异步函数,随后想要打印 return 值。如果我只是 await
来自顶层的 return 值,那么我会得到一个错误,说我只能在异步函数本身内部使用 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.whosebug.com/transcript/message/54186176#54186176)
这行得通 - 但我想更多地了解其背后的原因:我已经习惯了无法直接从顶层使用 await
。然而,我也习惯于不得不调用一些特殊的库函数来真正从顶层“冒险”进入异步。在 Python 中,例如参见 [=21=]。要求 await
在异步函数中有什么意义 - 如果我可以从顶层调用任何异步函数?为什么 await
也不能在顶层使用?
Top-level await used 不是问题,但现在在 ES6 模块中是可能的。
为什么 top-level await 过去不是,现在仍然不是模块之外的一个原因是它可能允许语法歧义。 在模块之外。如果 non-module 脚本允许 top-level await,那么,缺少 re-working 规范(并破坏向后兼容性),在某些情况下解析器无法确定特定实例是否await
是一个变量名,或者被用作等待 right-hand 端的 Promise 解析的语法。
为了避免任何歧义的可能性,解析器在解析一段代码时,本质上需要有标志来指示 await
在任何给定点作为标识符是否有效,或者它是否有效作为异步语法,这两者绝不能相交。
Module scrips允许top-level await(现在),因为它们一直禁止使用await作为标识符,所以不存在语法歧义。
相比之下,在顶层使用 .then
的问题为零,因为它在任何情况下都不会导致任何歧义。
Why doesn't it just return a Promise which is never executed because it doesn't get awaited?
承诺并没有真正“执行”。它们可以被构建,或等待实现,或等待拒绝。如果您有 Promise,那么您已经有一些正在进行的代码(可能)最终会导致将 fulfillment 值分配给 Promise。
Hanging Promises 在句法上是允许的 - 解析为 Promises 但不与其他地方交互的值。 (这是有道理的 - every .then
or .catch
产生一个新的 Promise。如果每个 Promise 都必须被其他东西使用,你最终会得到一个无限倒退。)
正在做
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
本质上是
的语法糖
someOtherAsyncFunc()
.then((foo) => {
console.log(foo);
});
没有必要在其中任何一个的末尾附加任何其他内容。 (尽管建议向悬挂的 Promise 添加 .catch
,这样未处理的拒绝就不会发生)
我有一个简短的 Node.js 脚本,我需要另一个包并从中调用一个异步函数,随后想要打印 return 值。如果我只是 await
来自顶层的 return 值,那么我会得到一个错误,说我只能在异步函数本身内部使用 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.whosebug.com/transcript/message/54186176#54186176)
这行得通 - 但我想更多地了解其背后的原因:我已经习惯了无法直接从顶层使用 await
。然而,我也习惯于不得不调用一些特殊的库函数来真正从顶层“冒险”进入异步。在 Python 中,例如参见 [=21=]。要求 await
在异步函数中有什么意义 - 如果我可以从顶层调用任何异步函数?为什么 await
也不能在顶层使用?
Top-level await used 不是问题,但现在在 ES6 模块中是可能的。
为什么 top-level await 过去不是,现在仍然不是模块之外的一个原因是它可能允许语法歧义。 await
是一个变量名,或者被用作等待 right-hand 端的 Promise 解析的语法。
为了避免任何歧义的可能性,解析器在解析一段代码时,本质上需要有标志来指示 await
在任何给定点作为标识符是否有效,或者它是否有效作为异步语法,这两者绝不能相交。
Module scrips允许top-level await(现在),因为它们一直禁止使用await作为标识符,所以不存在语法歧义。
相比之下,在顶层使用 .then
的问题为零,因为它在任何情况下都不会导致任何歧义。
Why doesn't it just return a Promise which is never executed because it doesn't get awaited?
承诺并没有真正“执行”。它们可以被构建,或等待实现,或等待拒绝。如果您有 Promise,那么您已经有一些正在进行的代码(可能)最终会导致将 fulfillment 值分配给 Promise。
Hanging Promises 在句法上是允许的 - 解析为 Promises 但不与其他地方交互的值。 (这是有道理的 - every .then
or .catch
产生一个新的 Promise。如果每个 Promise 都必须被其他东西使用,你最终会得到一个无限倒退。)
正在做
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
本质上是
的语法糖someOtherAsyncFunc()
.then((foo) => {
console.log(foo);
});
没有必要在其中任何一个的末尾附加任何其他内容。 (尽管建议向悬挂的 Promise 添加 .catch
,这样未处理的拒绝就不会发生)