worker线程通过定时心跳消息与performance.now()实现主线程卡顿监控:主线程每500ms发送带时间戳的心跳,worker检测超时(>1200ms)并记录连续超时次数;同时worker主动测量自身调度延迟,结合两者交叉验证卡顿事件。

Worker线程无法直接访问主线程的 DOM 或全局对象(如 window、document),但可以通过定时消息通信模拟“心跳检测”,并结合 performance.now() 和 self.performance 实现轻量级性能监控。核心思路是:主线程定期发心跳消息,Worker 记录时间戳并计算延迟/间隔异常;同时 Worker 可主动采集自身执行耗时,辅助判断主线程是否卡顿。
主线程:发送心跳并上报关键性能指标
主线程用 setInterval 定期向 Worker 发送带时间戳的消息,同时可附带当前帧率估算或任务队列状态:
- 使用
performance.now()生成高精度发送时间(避免Date.now()精度不足) - 每 500ms 发一次心跳,携带
{ type: 'heartbeat', ts: performance.now(), fp: window?.requestIdleCallback ? 'idle' : 'busy' } - 可选:在
requestAnimationFrame回调中补充帧渲染时间(performance.getEntriesByType('paint'))并一并发送
Worker线程:接收心跳、计算延迟并触发告警
Worker 维护上一次收到心跳的时间,在每次 onmessage 中比对间隔,识别长时间无响应:
- 初始化
let lastHeartbeat = 0,收到消息后更新为data.ts - 若
performance.now() - lastHeartbeat > 1200(即超时 2 倍心跳周期),视为疑似卡顿,可postMessage({ type: 'alert', reason: 'heartbeat timeout' }) - 记录连续超时次数,避免偶发抖动误报;3 次连续超时可触发降级策略(如暂停非关键上报)
Worker主动监控:测量自身调度延迟反推主线程压力
Worker 无法读取主线程堆栈,但可通过“自我调度延迟”间接反映主线程繁忙程度:
- 在 Worker 内启动一个
setInterval(() => { const now = performance.now(); postMessage({ type: 'self-check', delay: now - expected }); }, 100) -
expected是理论执行时间(如上一次 + 100),若实际delay > 200ms,说明 Worker 也被系统延迟调度,大概率因主线程长期占用 JS 引擎(尤其在低配设备上) - 配合主线程心跳数据,交叉验证:心跳停滞 + Worker 自身延迟升高 → 高置信度卡顿事件
数据聚合与简易可视化(可选)
Worker 可缓存最近 60 秒的心跳延迟数组,压缩后传回主线程用于绘图:
- 不实时传原始数据,改用滑动窗口统计:每 5 秒计算平均延迟、P95 延迟、超时次数
- 主线程收到聚合数据后,用
<canvas></canvas>绘制折线图,或仅在控制台输出console.warn('UI blocked for 1.8s at 14:22:03') - 避免在 Worker 中做复杂计算或 DOM 操作,保持其轻量——它只负责采集和粗筛
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











