在 ECMAScript 2022 (ES13) 中,JavaScript 引入了一项重要特性:顶层 await。这项功能允许开发者在模块的顶层直接使用 await
关键字,而不必将其包裹在异步函数中。这一改进极大地简化了异步代码的编写方式,特别是在模块初始化场景中。
什么是顶层 await?
传统上,await
关键字只能在 async
函数内部使用。这意味着如果我们需要在模块顶层等待异步操作完成,必须将代码包裹在立即调用的异步函数表达式(IIFE)中:
javascript
// ES2021 及之前的方式
(async function() {
const data = await fetchData();
console.log(data);
})();
ES2022 允许我们直接在模块顶层使用 await
:
javascript
// ES2022 顶层 await
const data = await fetchData();
console.log(data);
为什么需要顶层 await?
- 简化模块初始化:许多模块需要在加载时执行异步操作(如读取配置、初始化数据库连接等)
- 消除样板代码:不再需要包裹异步 IIFE
- 更直观的代码流:异步操作可以像同步代码一样线性表达
使用场景
1. 动态模块导入
javascript
const module = await import('/modules/my-module.js');
2. 资源初始化
javascript
const connection = await connectToDatabase();
export { connection };
3. 配置加载
javascript
const config = await fetch('/config.json').then(res => res.json());
export { config };
注意事项
- 仅限模块:顶层 await 只能在 ES 模块中使用,不能在普通脚本中使用
- 模块执行顺序:使用顶层 await 的模块会成为异步模块,可能影响依赖它的其他模块的执行时机
- 错误处理:需要在顶层使用 try-catch 处理可能的拒绝
javascript
try {
const data = await fetchData();
} catch (error) {
console.error('初始化失败:', error);
}
浏览器和 Node.js 支持
- 现代浏览器(Chrome 89+、Firefox 89+、Safari 15+)已支持
- Node.js 从 14.8.0 开始支持(需要 ES 模块,文件扩展名为 .mjs 或 package.json 中 type 为 "module")
结论
ES2022 的顶层 await 特性为 JavaScript 模块带来了更简洁、更直观的异步编程方式。它特别适合模块初始化场景,消除了许多样板代码,使异步资源加载和初始化更加自然。随着现代浏览器和 Node.js 的广泛支持,开发者现在可以安全地在生产环境中使用这一特性。
需要注意的是,虽然顶层 await 提供了便利,但仍应谨慎使用,特别是在需要考虑模块加载性能和依赖关系的情况下。合理使用这一特性可以显著提升代码的可读性和维护性。