JavaScript异步编程与性能优化是一体两面:async适合独立脚本,defer保障顺序执行;代码分割按需加载;Promise控制并发与错误;重任务移交Web Worker,DOM操作批量处理并配合防抖节流。

JavaScript 异步编程与性能优化不是两个独立课题,而是一体两面:异步是手段,性能是目标。真正高效的方案,必须同时解决“如何不阻塞主线程”和“如何减少资源浪费”这两个核心问题。
用对 async/defer,从加载阶段就赢一半
很多性能问题其实在页面还没开始执行 JS 时就埋下了——脚本阻塞 HTML 解析,导致白屏延长。关键不在“要不要异步”,而在“谁该 async、谁该 defer”:
- async适合完全独立、无依赖、也不操作 DOM 的脚本,比如统计埋点、错误监控;它一加载完就执行,不保证顺序
- defer适合有明确执行顺序的业务脚本(如 library.js → app.js),它等 DOM 解析完、在 DOMContentLoaded 前按顺序执行
- 避免在 async 脚本里直接访问
document.body等元素;如需操作 DOM,应监听DOMContentLoaded或用document.readyState判断
代码分割 + 动态导入,让 JS 真正按需加载
打包后一个几 MB 的 bundle.js 是性能杀手。现代构建工具(Webpack/Rollup/Vite)支持细粒度的代码分割,但关键在于“切在哪”和“怎么触发”:
- 路由级分割最常用:React 中用
lazy()+Suspense,Vue 中用defineAsyncComponent - 组件级分割更精细:例如只在用户点击“导出报表”按钮后,才加载
xlsx库 - 条件加载更灵活:结合
import()动态导入,配合用户行为或设备特征(如仅在桌面端加载富文本编辑器)
Promise 和 async/await 不只是写法,更是控制流设计
写法简洁只是表象,真正的性能价值在于可控的并发、可预测的错误边界和清晰的执行节奏:
立即学习“Java免费学习笔记(深入)”;
- 并行请求用
Promise.all(),但注意失败会全盘中断;需要容错时改用Promise.allSettled() - 串行依赖用
await链,避免把多个 await 写成同步式嵌套;也别滥用await,无依赖的请求应尽量并行 - 错误必须显式捕获:
try/catch包裹await,或给 Promise 链配.catch();未处理的 rejected Promise 会静默失败,且可能拖慢后续微任务
避开主线程陷阱,把重活交给合适的地方
再好的异步写法,也救不了一个耗时 200ms 的同步计算。性能瓶颈常藏在“看不见”的地方:
- 大数据量遍历、排序、解析 JSON —— 考虑用
Web Worker移出主线程,避免 UI 卡顿 - 频繁 DOM 更新(如实时图表渲染)—— 用
requestIdleCallback()或setTimeout(..., 0)让渡控制权,或批量更新 +DocumentFragment - 防抖/节流不是锦上添花,而是刚需:搜索输入、滚动监听、窗口缩放,必须加限制,否则几十次回调瞬间压垮主线程



















