Javascript 在异步函数之外使用 await

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39679505/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:48:13  来源:igfitidea点击:

Using await outside of an async function

javascriptnode.jsasync-await

提问by Sterling Archer

I was attempting to chain two async functions together, because the first had a conditional return parameter that caused the second to either run, or exit the module. However, I've found odd behavior I can't find in the specs.

我试图将两个异步函数链接在一起,因为第一个有一个条件返回参数,导致第二个要么运行,要么退出模块。但是,我发现了在规范中找不到的奇怪行为。

async function isInLobby() {
    //promise.all([chained methods here])
    let exit = false;
    if (someCondition) exit = true;
}

This is a bastardized snippet of my code (you can see the full scope here), that simply checks if a player if already in a lobby, but that's irrelevant.

这是我的代码的一个混蛋片段(您可以在此处查看完整范围),它只是检查玩家是否已经在大厅中,但这无关紧要。

Next we have this async function.

接下来我们有这个异步函数。

async function countPlayer() {
    const keyLength = await scardAsync(game);
    return keyLength;
}

This function doesn't need to run if exit === true.

这个函数不需要运行 if exit === true

I tried to do

我试着做

const inLobby = await isInLobby();

This I hoped would await to results, so I can use inLobbyto conditionally run countPlayer, however I received a typeerror with no specific details.

我希望这会等待结果,所以我可以inLobby用来有条件地运行countPlayer,但是我收到了一个没有具体细节的类型错误。

Why can't you awaitan asyncfunction outside of the scope of the function? I know it's a sugar promise, so it must be chained to thenbut why is it that in countPlayerI can await another promise, but outside, I can't awaitisInLobby?

为什么你不能awaitasync函数范围之外的函数?我知道这是一个甜蜜的承诺,所以它必须被链接起来,then但为什么countPlayer我可以等待另一个承诺,但在外面,我不能awaitisInLobby

采纳答案by Andy Ray

Top level awaitis not supported. There are a few discussions by the standards committee on why this is, such as this Github issue.

await不支持顶级。标准委员会对此进行了一些讨论,例如这个 Github 问题

There's also a thinkpiece on Githubabout why top level await is a bad idea. Specifically he suggests that if you have code like this:

Github上还有一篇关于为什么顶级 await 是个坏主意的想法。具体来说,他建议如果你有这样的代码:

// data.js
const data = await fetch( '/data.json' );
export default data;

Now anyfile that imports data.jswon't execute until the fetch completes, so all of your module loading is now blocked. This makes it very difficult to reason about app module order, since we're used to top level Javascript executing synchronously and predictably. If this were allowed, knowing when a function gets defined becomes tricky.

现在任何导入的文件data.js在获取完成之前都不会执行,因此所有模块加载现在都被阻止了。这使得推断应用模块顺序变得非常困难,因为我们习惯于同步和可预测地执行顶级 Javascript。如果允许这样做,那么知道何时定义函数就变得棘手了。

My perspectiveis that it's bad practice for your module to have side effects simply by loading it. That means any consumer of your module will get side effects simply by requiring your module. This badly limits where your module can be used. A top level awaitprobably means you're reading from some API or calling to some service at load time.Instead you should just export async functions that consumers can use at their own pace.

我的观点是,您的模块仅仅通过加载就产生副作用是不好的做法。这意味着您的模块的任何使用者都会因为需要您的模块而获得副作用。这严重限制了您的模块的使用范围。顶级await可能意味着您正在读取某些 API 或在加载时调用某些服务相反,您应该只导出消费者可以按照自己的节奏使用的异步函数。

回答by digerati-stratagies

There is always this of course:

当然总是有这个:

(async () => {
    await ...

    // all of the script.... 

})();
// nothing else

This makes a quick function with async where you can use await. It saves you the need to make an async function which is great! //credits Silve2611

这使您可以在其中使用等待的异步快速功能。它使您无需制作一个很棒的异步函数!//信用Silve2611

回答by Viliam Simko

Even better is to put additional semicolon in front of the code block

更好的是在代码块前面添加额外的分号

;(async () => {
    await ...
})();

This prevents auto-formatter (e.g. in vscode) to move the first parenthese to the end of the previous line.

这可以防止自动格式化程序(例如在 vscode 中)将第一个括号移动到前一行的末尾。

The problem can be demonstrated on the following example:

可以在以下示例中演示该问题:

const add = x => y => x+y
const increment = add(1)
(async () => {
    await ...
})();

Without the semicolon, this will be re-formatted as:

如果没有分号,这将被重新格式化为:

const add = x => y => x+y
const increment = add(1)(async () => {
  await Promise(1)
})()

which obviously is wrong because it assigns the async function as the yparameter and tries to call a function from the result (which is actually a weird string '1async () => {...}')

这显然是错误的,因为它将异步函数分配为y参数并尝试从结果中调用函数(实际上是一个奇怪的字符串'1async () => {...}'

回答by AXE

you can do top level await since typescript 3.8
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
From the post:
This is because previously in JavaScript (along with most other languages with a similar feature), await was only allowed within the body of an async function. However, with top-level await, we can use await at the top level of a module.

您可以从 typescript 3.8
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
从帖子中执行顶级等待:
这是因为以前在JavaScript(以及具有类似功能的大多数其他语言),await 仅允许在异步函数的主体内使用。但是,使用顶级 await,我们可以在模块的顶级使用 await。

const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);

// Make sure we're a module
export {};

Note there's a subtlety: top-level await only works at the top level of a module, and files are only considered modules when TypeScript finds an import or an export. In some basic cases, you might need to write out export {} as some boilerplate to make sure of this.

请注意,有一个微妙之处:顶级 await 仅在模块的顶级工作,并且文件仅在 TypeScript 找到导入或导出时才被视为模块。在某些基本情况下,您可能需要将 export {} 写为样板文件以确保这一点。

Top level await may not work in all environments where you might expect at this point. Currently, you can only use top level await when the target compiler option is es2017 or above, and module is esnext or system. Support within several environments and bundlers may be limited or may require enabling experimental support.

顶级 await 可能不适用于您此时可能期望的所有环境。目前只能在目标编译器选项为es2017及以上,模块为esnext或system的情况下使用顶级await。多个环境和捆绑器中的支持可能有限,或者可能需要启用实验性支持。

回答by Mike B.

As of Node.js 14.3.0the top-level await is supported.

从 Node.js 14.3.0 开始,支持顶级 await。

Required flag: --experimental-top-level-await.

所需标志:--experimental-top-level-await.

Further details: https://v8.dev/features/top-level-await

更多详情:https: //v8.dev/features/top-level-await