async/await 通过包装模块导入为 promise 实现精准加载控制,配合动态 import() 按需加载、promise.all() 并行、promise.race() 降级,并支持 async init() 延迟初始化,需规避顶层 await、错误捕获及异步循环陷阱。

async/await 本身不直接加载模块,但它能精准控制模块加载的时机和依赖顺序——关键在于把模块导入(import)或初始化逻辑包装成 Promise,并用 await 主动等待其就绪。
动态 import() 是 async/await 的搭档
ES2020 起,import() 返回一个 Promise,天然适配 await:
- 不能写
import module from './a.js'(这是静态语法,编译期执行,无法 await) - 必须用
const module = await import('./a.js'),在运行时按需加载并等待完成 - 适合按路由、功能开关或用户行为触发的模块加载,比如点击“报表”按钮后才加载 charting 模块
处理多模块的串行与并行依赖
根据依赖强弱决定加载策略:
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
- 强依赖(如工具库必须先于业务模块加载):逐个 await,保证顺序
await import('./utils.js');<br>await import('./report-module.js'); - 弱依赖(如多个独立组件、语言包、埋点 SDK):用 Promise.all() 并行加载
const [ui, i18n, tracker] = await Promise.all([<br> import('./ui-kit.js'),<br> import('./locales/zh-CN.js'),<br> import('./analytics.js')<br>]); - 任一失败可降级:用 Promise.race([p, timeout(3000)]) 避免卡死
结合模块导出的 async 初始化函数
模块不只导出对象,还可导出 async init() 方法,把副作用(如 API 预热、配置拉取)推迟到真正需要时:
- 子模块暴露:
export async function init() {<br> const config = await fetch('/api/config');<br> return config.json();<br>} - 主模块按需调用:
const mod = await import('./feature.js');<br>const cfg = await mod.init(); // 等待业务级就绪,不只是代码加载完 - 这样既解耦了加载与初始化,又让依赖关系显式、可中断、可重试
避免常见陷阱
几个容易出错但很典型的点:
- 不能在顶层 await:模块顶层作用域不允许 await(除非是 ES 模块顶层 await,仅限支持环境且需明确配置);稳妥做法是封装进 async 函数或 IIFE
-
循环中不能直接 await 回调:如
arr.forEach(async item => await load(item))不会按序等待;改用for...of或map().then(Promise.all()) - 错误必须 try/catch:动态 import 失败会 reject,不捕获会导致 unhandled rejection;尤其网络异常或路径错误时
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










