在异步函数之外使用 await

IT技术 javascript node.js async-await
2021-01-19 17:35:31

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

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

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

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

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

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

我试着做

const inLobby = await isInLobby();

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

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

4个回答

当然总是有这个:

(async () => {
    await ...

    // all of the script.... 

})();
// nothing else

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

对这个答案投反对票是非常愚蠢的。它使用 async 制作了一个快速功能,您可以在其中使用 await。它使您无需制作一个很棒的异步函数!
2021-03-27 17:35:31
那么这将如何处理错误情况?它也落在等待代码中吗?
2021-03-27 17:35:31
不能解决问题,因为您仍然需要await这个匿名函数,它同样在函数外部不起作用。
2021-03-28 17:35:31
请进一步详细说明并解释为什么会这样。
2021-04-02 17:35:31
Tks 这很有帮助,特别是回调promise once fetch login API,完美响应获取存储getItem
2021-04-13 17:35:31

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

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

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

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

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

这是一个很好的链接,谢谢。很遗憾没有顶级支持。我希望是。目前,我必须在这里兑现我的Promise,这是非常糟糕的做法,我不喜欢它。:( 谢谢。
2021-03-19 17:35:31
@robertklep 不会是inLobby该函数的范围使其不可访问吗?
2021-03-29 17:35:31
@SterlingArcher 是的,它会要求您将所有代码移动到那里(基本上使其成为“顶级”)。它只是使用的替代方法.then()(抱歉,应该更清楚一点)。
2021-04-06 17:35:31
不同意,data.js 的用户在加载 data.js 本身及其所有依赖项时被“阻塞”,这种“阻塞”的概念本身并不坏。顶级 await 可以被视为加载一些依赖项,在“释放”使用之前似乎需要具有这些依赖项。
2021-04-06 17:35:31
@SterlingArcher 或者,使用异步 IIFE: void async function() { const inLobby = await isInLobby() }()
2021-04-11 17:35:31

从 Node.js 开始14.3.0,顶级 await 支持一个标志:

--experimental-top-level-await

从 Node.js 16.12.0/ 开始17.0.0,不需要标志。

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

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

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

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

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

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

对于普通 JavaScript 也是如此。在节点,你要确保你有"type": "module"你的顶部package.json使用.jsm文件扩展名。
2021-03-28 17:35:31