直接看任务在主线程上实际占用时长,超50ms即为长任务并导致用户可感知卡顿;可通过Chrome Performance面板抓取火焰图定位、PerformanceObserver监听线上长任务、User Timing打点精细化测量,同时警惕高频伪短任务对帧率的累积影响。

直接看任务在主线程上实际占用了多久,重点不是“它属于宏任务还是微任务”,而是“它有没有卡住页面响应”。超过 50ms 就算长任务,用户能明显感知卡顿。
用 Performance 面板抓取真实耗时
打开 Chrome DevTools → Performance 标签页 → 点击录制(●)→ 操作页面(比如滚动、点击、加载数据)→ 停止录制。在火焰图(Flame Chart)里找红色长条,鼠标悬停就能看到具体耗时、调用栈和任务类型(如 “Timer Fired” 对应 setTimeout,“Promise.then” 属于微任务)。顶部 Summary 面板会直接标出所有 >50ms 的 Long Task。
用 PerformanceObserver 主动监听
适合线上埋点或自动化检测,代码简单可靠:
- 创建观察器监听 longtask 类型条目
- 每个条目包含 duration(毫秒)、startTime、attribution(触发来源,如 script、timer、input)
- 可结合上报逻辑,统计 TBT(总阻塞时间)或定位高频长任务模块
示例代码:
立即学习“Java免费学习笔记(深入)”;
list.getEntries().forEach(entry => {
console.log(`长任务 ${entry.duration.toFixed(1)}ms,来自 ${entry.attribution}`);
});
});
observer.observe({ entryTypes: ['longtask'] });
结合 User Timing 手动打点
对关键逻辑段落做精细化测量,比如“解析 10 万条数据”或“渲染列表首屏”:
- 用 performance.mark() 在起点和终点打标记
- 用 performance.measure() 计算两点间耗时
- 结果可在 Performance 面板的 User Timing 轨道中直观查看,也能用 performance.getEntriesByName() 获取数据
注意:mark 和 measure 都是轻量操作,不影响主线程,但别在高频循环里滥用。
警惕“伪短任务”陷阱
有些任务单次不长,但高频连续执行,照样拖慢帧率:
- 滚动事件里没节流的计算,每帧都跑一次 → 看似每次 5ms,但 60fps 下每秒 60 次,等于持续占用主线程
- 大量 Promise 链式调用,虽然每个 then 很快,但微任务队列堆积导致后续宏任务延后
- 频繁触发 layout thrashing(强制同步布局),比如读 style 又改 DOM 再读,浏览器反复重排
这类问题光看单个任务耗时不全面,得配合 FPS 曲线和 Layout/Recalculate Style 时间一起分析。


















