Top-level await 允许在 ESModule 顶层直接使用 await,但仅限模块环境且会阻塞模块及其静态导入链执行;需通过 type="module"、.mjs 或 "type": "module" 启用,CommonJS 不支持。

ESModule 中的 Top-level await 允许你在模块顶层直接使用 await,无需包裹在 async 函数里。但要注意:它只在 ESModule 环境下有效,且会阻塞该模块及其所有静态导入链的执行,直到 Promise 解析完成。
必须是 ESModule 才能启用 Top-level await
浏览器或 Node.js 中需明确启用模块模式:
- 浏览器中:HTML 脚本标签必须带
type="module",例如<script type="module" src="main.js"></script> - Node.js 中:文件后缀为
.mjs,或package.json中设置"type": "module" - CommonJS(
.cjs或"type": "commonjs")不支持 Top-level await,会报语法错误
Top-level await 的执行时机和影响
它不是“等完再执行模块代码”,而是让整个模块变成异步模块 —— 模块本身返回一个 Promise,其导出(export)只有在 await 完成后才可用:
// config.mjs
const res = await fetch('/api/config');
export const config = await res.json(); // ✅ 合法:顶层 await + export
此时,任何 import 这个模块的地方,都会等待 config 就绪后才继续执行:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
// main.mjs
import { config } from './config.mjs'; // ⏳ 这行会等到 config.mjs 的 await 完成
console.log(config); // ✅ 此时 config 已确定存在且已解析
常见用途:异步初始化、环境配置、权限检查
适合用于模块级的一次性异步准备逻辑:
- 加载远程配置或翻译资源:
export const i18n = await import(`./locales/${lang}.json`) - 检查用户登录态或权限:
const user = await auth.getUser(); if (!user) throw new Error('Not authorized'); - 预加载关键数据或缓存:
export const cache = await initCache();
⚠️ 注意:不要滥用。若 await 的 Promise 长时间不 resolve,整个模块导入链都会卡住,影响页面启动或依赖加载。
不能和 CommonJS 混用,也不能在动态 import 外写普通顶层 await
以下写法均 ❌ 错误:
-
require('./foo.cjs')后试图用await—— CommonJS 不支持 - 在非模块脚本(
type="text/javascript")中写await Promise.resolve()—— 语法错误 - 在函数外写
await,但模块未被识别为 ESM(比如 Node.js 忘记设"type": "module")
可通过 import.meta.url 判断当前是否为 ESM 环境,但无法绕过语法限制。

















