admin管理员组文章数量:1279083
I have a short Node.js script where I require another package and call an async function from it and subsequently want to print the return value. If I simply await
the return value from the top level, then I'll get an error, saying that I can only use await
inside an async function itself. So apparently the way to go is like this:
async function main() {
foo = await someOtherAsyncFunc();
console.log(foo);
}
main()
Or:
(async function() {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
Or:
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
(Credit to VLAZ in chat )
This works - but I want to understand the reasons behind it a little bit more: I'm used to not being able to directly use await
from the top level. However, I'm also used to having to call some special library function to actually "venture" into async from the top level. In Python, see asyncio.run
for example. What's the point of requiring await
to be inside an async function - if I can then call just any async function from the top level? Why then isn't await
available at top level, too?
I have a short Node.js script where I require another package and call an async function from it and subsequently want to print the return value. If I simply await
the return value from the top level, then I'll get an error, saying that I can only use await
inside an async function itself. So apparently the way to go is like this:
async function main() {
foo = await someOtherAsyncFunc();
console.log(foo);
}
main()
Or:
(async function() {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
Or:
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
(Credit to VLAZ in chat https://chat.stackoverflow./transcript/message/54186176#54186176)
This works - but I want to understand the reasons behind it a little bit more: I'm used to not being able to directly use await
from the top level. However, I'm also used to having to call some special library function to actually "venture" into async from the top level. In Python, see asyncio.run
for example. What's the point of requiring await
to be inside an async function - if I can then call just any async function from the top level? Why then isn't await
available at top level, too?
- 2 v8.dev/features/top-level-await – Patrick Roberts Commented Mar 17, 2022 at 18:58
- 1 stackoverflow./questions/39679505/… – James Commented Mar 17, 2022 at 18:58
-
An
async
function is simply a function that returns a Promise. Theawait
keyword is there to introduce, basically, a.then()
call around the rest of the code in the function. Thus, when you call anasync
function but don'tawait
it, that's fine, because eventually the Promise will resolve (or reject) and the rest of the code in the function will run. – Pointy Commented Mar 17, 2022 at 19:08 -
I think the answer may be related to the fact that top-level await used to not be a thing is that there weren't any natural approaches for downstream scripts to consume results from a script that uses top-level await. It doesn't make much sense to try to export something after an
await
, for example. – CertainPerformance Commented Mar 17, 2022 at 19:11 - Does this answer your question? Using await outside of an async function – 0Valt Commented Mar 17, 2022 at 20:12
1 Answer
Reset to default 9Top-level await used to not be a thing, but it is possible now in ES6 modules.
One reason why top-level await used to not be a thing, and is still not a thing outside of modules is that it could permit syntactical ambiguity. Async and await are valid variable names. outside of modules. If a non-module script permitted top-level await, then, short of re-working the specification (and breaking backwards patibility), there would be circumstances when the parser couldn't determine whether a particular instance of await
was a variable name, or was used as the syntax to wait for the Promise on its right-hand side to resolve.
To avoid any possibility of ambiguity, the parser, when parsing a section of code, essentially needs to have flags that indicate whether await
is valid as an identifier at any given point, or whether it's valid as async syntax, and those two must never intersect.
Module scrips permit top-level await (now) because the use of await as an identifier has always been forbidden in them, so there is no syntactical ambiguity.
In contrast, there are zero issues with using .then
on the top level because it doesn't result in any ambiguity in any circumstances.
Why doesn't it just return a Promise which is never executed because it doesn't get awaited?
Promises aren't really "executed". They can be constructed, or waited on to fulfill, or waited on to reject. If you have a Promise, you already have some ongoing code that will (probably) eventually result in a fulfillment value being assigned to the Promise.
Hanging Promises are syntactically permitted - values that resolve to Promises but which aren't interacted with elsewhere. (Which makes sense - every .then
or .catch
produces a new Promise. If every Promise had to be used by something else, you'd end up with an infinite regress.)
Doing
(async () => {
foo = await someOtherAsyncFunc();
console.log(foo);
})();
is essentially syntax sugar for
someOtherAsyncFunc()
.then((foo) => {
console.log(foo);
});
There's no need to tack anything else onto the end of either of those. (though it's remended to add a .catch
to a dangling Promise so unhandled rejections don't occur)
本文标签:
版权声明:本文标题:javascript - Because I can't run await on the top level, I have to put it into an async function - why can I then call t 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741281188a2370015.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论