Skip to content

PerformanceObserver 与长任务 ​

本节用 PerformanceObserver 收集长任务条目,并明确“没有条目”与“观察器失效”的区别。

js
const entries = []
const supported = typeof PerformanceObserver !== 'undefined' && PerformanceObserver.supportedEntryTypes?.includes('longtask')
if (supported) {
  const observer = new PerformanceObserver(list => entries.push(...list.getEntries()))
  observer.observe({ type: 'longtask', buffered: true })
  const end = performance.now() + 60
  while (performance.now() < end) {}
  setTimeout(() => { console.log(entries.map(entry => entry.duration)); observer.disconnect() }, 0)
} else {
  console.log('longtask unsupported')
}

支持 longtask 的浏览器应记录至少一个超过 50ms 的条目;不支持该类型时记录能力差异,不把空数组当成优化成功。

机制拆解 ​

PerformanceObserver 异步接收指定类型的性能条目。longtask 反映主线程超过阈值的任务,不等于一次交互的总耗时;需要制造对照、记录浏览器是否支持并在完成后断开观察器。

边界与失败路径 ​

  • 所有权:监听器、observer、worker、连接、缓存和焦点都有创建者与释放时机;页面隐藏、路由离开和元素移除时都要验证。
  • 宿主差异:SSR、Web Worker、Shadow DOM、跨文档、跨源和辅助技术不会共享同一套全局对象与事件路径。
  • 错误分类:取消、超时、权限拒绝、协议错误、配额不足和浏览器不支持应分别进入可观察状态。
  • 安全边界:用户输入、URL、HTML、消息和持久化数据不能仅因为来自同源或类型正确就视为可信。

可运行实验 ​

先运行 60ms 同步循环制造 longtask,再移除循环;记录条目数量、duration 和浏览器支持情况,最后调用 disconnect() 验证观察器不再追加日志。

实验记录要包含运行时、输入步骤、预期输出、实际日志和未覆盖的宿主差异。

练习 ​

  1. 制造超过 50ms 的循环,记录 longtask 条目 duration。
  2. 移除循环并断言条目为空或明显减少,最后 disconnect。
  3. 区分 PerformanceObserver 条目、页面总响应时间和 FPS。 查看本节答案

下一步 ​

完成练习后回到本章概览,按下一篇继续;遇到跨章节故障,先回到本节的所有权与宿主边界。

用心记录每一步成长