全局调用异步函数时出错:“等待仅在异步函数和模块的顶层主体中有效”?

Posted

技术标签:

【中文标题】全局调用异步函数时出错:“等待仅在异步函数和模块的顶层主体中有效”?【英文标题】:Error in global call to async function: "await is only valid in async functions and the top level bodies of modules"? 【发布时间】:2021-08-13 17:35:15 【问题描述】:

在我开始之前,我承认有几个关于 SO 的问题听起来可能与我的标题相似相似,但是,我阅读的所有问题都更多 比我的代码复杂,而且解释似乎与我的情况无关。

谁能帮我理解我的代码(下面的sn-p)中发生了什么导致这个错误:

未捕获的语法错误:await 仅在异步函数中有效,并且 模块的顶层主体。

据我所见,导致错误的await 在“***”正文中。还是***机构的其他含义?非常感谢!

EDIT 区别于其他建议的(类似)问题here:我的问题不涉及 httpGet,其他一些上下文不同,最重要的是我收到了答案这为我解决了这个问题,与另一个问题的(单独)答案中给出的建议不同。因此,虽然我能够在这里找到解决方案,但我相信保留我的问题对于普通观众来说是有价值的。

var data;
await getData();
document.body.write(data);

async function getData() 
    const res = await fetch("https://jsonplaceholder.typicode.com/posts", 
        method: 'GET',
        headers: 
          'Accept': 'application/json, text/plain, */*',
          'Content-type': 'application/json'
        
    );
    data = await res.json();

【问题讨论】:

of modules — 这可能不是一个模块,而只是全局代码? 它肯定不是栈 sn-p 中的一个模块。 是否需要将 fetch 调用封装在 getData() 方法中? 这能回答你的问题吗? How to resolve the Syntax error : await is only valid in async function? 它没有,因此它是评论而不是我的答案的一部分。 【参考方案1】:

***await 表示您正在尝试在async 函数之外使用async/await 语法。解决方法是创建一些功能,例如main 并把代码放进去。

async function main() 
  var data;
  await getData();
  document.body.write(data);


main();

有一天*** async/await 将得到支持,并且有一个提案。同时你可以使用这个 babel 插件来使用它 https://babeljs.io/docs/en/babel-plugin-syntax-top-level-await 没有像 main 这样的包装函数。

【讨论】:

谢谢。所以我只需要在它周围放一个包装,仅此而已?从句法/逻辑上讲,重点/区别是什么? 我的意思是,如果我在它周围放置一个包装器,那么我将需要从另一个函数调用它——我不想异步调用它。我希望在执行继续之前完成 fetch 调用并加载所有数据。有什么方法可以实现吗? 好吧,await 只是 Promises 的语法糖。它将等待 promise 解决,然后执行下面的代码,但由于 HTTP 请求是异步的,因此也可能会执行一些其他代码。所以它应该满足你的需要,它会等待getData 执行,然后document.body.write 调用将被执行。 这正是问题所在。如果我不等待,那么“一些其他代码”会在数据下载完成之前执行,这会导致不需要的行为。 您可以在脚本中调用包装器,包装器将包含您必须执行的所有代码,并且因为您输入了await,代码将在执行其他操作之前等待异步请求。如果您想移除异步行为,可以发出 HTTP 请求 sync【参考方案2】:

是的,它是全局代码 - 在我的 script.js 文件中。我想还有什么比这更“***”的呢?

正如评论中指出的,问题不是“***”而是“在模块中”。

只有当type 属性要求这样做时,Web 浏览器才会将脚本作为模块加载:

<script type="module" src="script.js"></script>

这启用了对import 的支持(CORS 允许),使脚本异步加载,并停止***作用域是全局的。

【讨论】:

谢谢!我尝试添加 type="module" 属性,到目前为止它似乎已经奏效了!脚本停止并等待函数调用完成,然后继续进行。所以有一个解决方案!我也很欣赏其他回复,但显然可以做到,不像他们所说的那样。

以上是关于全局调用异步函数时出错:“等待仅在异步函数和模块的顶层主体中有效”?的主要内容,如果未能解决你的问题,请参考以下文章

WPF异步回调时回调函数如何获取异步函数产生的变量

出错处理函数

调用异步任务芹菜时引发异常:“NameError:未定义全局名称*”

总结了一些指针易出错的常见问题

NodeJS 在异步函数(async/await)中调用栈打印不全的问题

更正 node.js 中的异步函数导出