在异步函数之外使用await

时间:2016-09-24 18:12:32

标签: javascript node.js async-await

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

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

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

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

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

如果exit === true

,则无需运行此功能

我试着做

const inLobby = await isInLobby();

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

为什么你不能await async函数范围之外的函数?我知道这是一个糖的承诺,所以它必须被链接到then,但为什么在countPlayer我可以等待另一个承诺,但在外面,我不能await {{1 }}?

5 个答案:

答案 0 :(得分:56)

当然总会如此:

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

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

答案 1 :(得分:44)

不支持顶级await。标准委员会就此进行了一些讨论,例如this Github issue

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

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

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

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

答案 2 :(得分:6)

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

必需标志:--experimental-top-level-await

更多详细信息:https://v8.dev/features/top-level-await

答案 3 :(得分:1)

更好的方法是在代码块前面添加分号

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

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

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

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

没有分号,它将重新设置为:

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

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

答案 4 :(得分:1)

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

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

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

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

顶层等待可能不适用于您此时可能期望的所有环境。当前,仅当目标编译器选项为es2017或更高版本且模块为esnext或system时,才可以使用顶级等待。在多个环境和捆绑软件中的支持可能会受到限制,或者可能需要启用实验性支持。