在异步函数之外使用await

Ste*_*her 53 javascript node.js async-await

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

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

这是我的代码的一个卑鄙的片段(你可以在这里看到完整的范围),它只是检查一个玩家是否已经在大厅,但这是无关紧要的.

接下来我们有这个异步功能.

async function countPlayer() {
    const keyLength = await scardAsync(game);
    return keyLength;
}
Run Code Online (Sandbox Code Playgroud)

如果这个函数不需要运行exit === true.

我试着这样做

const inLobby = await isInLobby();
Run Code Online (Sandbox Code Playgroud)

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

为什么你不能awaitasync函数范围之外的函数?我知道这是一个糖的承诺,所以它必须被束缚,then但为什么countPlayer我可以等待另一个承诺,但在外面,我不能await isInLobby

小智 80

当然总有这样:

(async () => {
    await ...
})();
Run Code Online (Sandbox Code Playgroud)

这使得可以使用等待的异步快速功能.它可以节省您制作非常棒的异步功能的需要!//信用Silve2611

  • 没有解决问题,因为你仍然需要`等待'这个匿名函数,这也不能从函数外部起作用. (40认同)
  • Downvote这个答案是非常愚蠢的.它使用async进行快速功能,您可以使用等待.它可以节省您制作非常棒的异步功能的需要! (8认同)
  • 请进一步详细说明并解释其工作原理。 (2认同)

And*_*Ray 53

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

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

// data.js
const data = await fetch( '/data.json' );
export default data;
Run Code Online (Sandbox Code Playgroud)

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

我的观点是,你的模块只需加载它就会产生副作用,这是不好的做法.这意味着您的模块的任何消费者只需要您的模块即可获得副作用.这严重限制了您的模块的使用位置.顶级await可能意味着您正在读取某些API或在加载时调用某些服务.相反,您应该只导出消费者可以按自己的节奏使用的异步功能.

  • 不同意,data.js 的用户在加载 data.js 本身及其所有依赖项时被“阻止”,这种“阻止”的概念本身并不坏。顶级等待可以被视为加载一些依赖关系,在使用“释放”之前似乎需要具有该依赖关系。 (2认同)

Mik*_* B. 9

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

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

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


小智 6

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

\n\n
const response = await fetch("...");\nconst greeting = await response.text();\nconsole.log(greeting);\n\n// Make sure we\'re a module\nexport {};\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

顶级等待可能无法在您目前期望的所有环境中工作。目前,只有当目标编译器选项为 es2017 或更高版本,并且模块为 esnext 或 system 时,才能使用顶级等待。多个环境和捆绑程序中的支持可能是有限的,或者可能需要启用实验支持。

\n

  • “.jsm”从来都不是有效的文件扩展名。这是`.mjs`。 (2认同)