长任务优化
长任务优化:拆分大任务、分片执行、Web Worker 卸载,避免主线程阻塞导致卡顿。
#type / concept
#status / evergreen
#tech / dev / frontend
[!info] related notes
- 所属 MOC: 前端性能优化 MOC
- 前置概念: browser-rendering-process
- 并列概念: composite-layer-animation, debounce-and-throttle
长任务优化
一句话定义
长任务优化是避免 JavaScript 单个任务执行太久导致主线程阻塞,引起点击无响应、输入卡顿、动画掉帧的优化技术。
核心内容
主线程在做什么
- JS 执行
- 样式计算
- 布局绘制
- 事件响应
长任务的危害
- 点击没反应
- 输入卡顿
- 动画掉帧
- 页面假死
优化思路
拆分大任务
将一个同步执行的大任务拆成多个小任务,分批执行:
// 原来:同步执行 10000 条数据
processData(data);
// 优化:分片执行
function processData(data) {
const chunkSize = 100;
let index = 0;
function process() {
const end = Math.min(index + chunkSize, data.length);
for (; index < end; index++) {
// 处理数据
}
if (index < data.length) {
requestAnimationFrame(process); // 或 setTimeout
}
}
process();
}
Web Worker 卸载
将重计算移到 Worker 线程:
适用场景:
- 大量计算
- 数据解析
- 文本处理
- 图像处理
- 大 JSON 转换
注意事项:
- 通信有成本(序列化/反序列化)
- 共享状态复杂
- 不适合所有业务逻辑
延后非关键逻辑
- 非首屏的初始化逻辑延后
- 统计/埋点等低优先级任务延后
边界与易混淆点
requestAnimationFrame vs setTimeout
- setTimeout:不和浏览器刷新节奏对齐,可能丢帧
- requestAnimationFrame:和浏览器刷新节奏对齐,更平滑
Web Worker 不是万能的
- 不适合需要频繁操作 DOM 的场景
- 通信成本需要注意