ES2022支持顶层await后async关键字还有哪些用途?
ES2022 支持顶层 await 后,async 关键字的实际作用与适用场景
首先先纠正一个普遍误解:顶层await的适用范围非常窄,仅能在ES模块的最外层作用域使用,从来没有开放所有场景下脱离async写await的权限,async的核心价值完全没有被顶层await替代,目前仍然是JavaScript异步编程里的核心关键字,常见适用场景如下:
- 为非顶层作用域提供await使用权限
除了ES模块的最外层,所有函数作用域(包括普通函数、箭头函数、对象方法、类方法、回调函数)、非模块脚本(普通script标签、CommonJS模块)的顶层,都不允许直接写await,只要你需要在这些位置使用await,就必须给对应的函数加上async关键字,这也是日常开发中最常用到async的场景。
示例代码:// 函数内部要使用await,必须标记async,否则直接抛语法错误 const fetchOrderList = async (pageNum) => { const resp = await fetch(`/api/order?page=${pageNum}`) return resp.json() } class DataService { // 类方法内部用await同样需要加async async getConfig() { return await localStorage.getItem('app_config') } } - 自动包装返回值为Promise,统一异步调用规范
所有被async标记的函数,无论内部返回的是普通同步值还是抛出同步错误,都会被自动包装为Promise对象:返回普通值对应fulfilled状态的Promise,抛出错误对应rejected状态的Promise,不需要开发者手动写Promise.resolve/Promise.reject做包装,调用方可以统一用await或者.then/.catch的方式处理结果,非常适合封装通用异步接口、打通同步/异步错误的处理链路。
示例代码:async function getStaticConfig() { // 直接返回普通对象,返回值会自动包装为Promise return { theme: 'light', pageSize: 20 } } // 可以直接用await获取结果 const config = await getStaticConfig() - 适配非模块环境的异步执行需求
顶层await仅在ES Module规范下生效,如果你开发的是CommonJS模块、或者页面中直接引入不带type="module"标记的普通脚本,压根不支持顶层await,所有初始化阶段的异步逻辑,都必须包裹在async自执行函数中才能运行:// 普通脚本/CommonJS中执行顶层异步逻辑的通用写法 (async () => { const initData = await loadAppInitData() mountApp(initData) })() - 明确语义标识,降低代码维护成本
函数签名上的async关键字是非常明确的语义标记:其他开发者看到这个标记,不需要通读函数内部实现,就能立刻知道这个函数返回Promise、调用时需要考虑异步等待、内部存在异步逻辑,能大幅降低代码的理解成本。这种作用是顶层await完全无法提供的——毕竟正常开发不可能把所有业务逻辑都堆在模块的最外层。
本质上顶层await只是解决了ES2022之前,模块顶层写异步逻辑必须额外包裹一层无意义async立即执行函数的痛点,完全没有替代async在函数维度的核心能力。
内容的提问来源于stack exchange,提问作者Sagar Darekar
相关产品推荐
相关产品推荐

