前端 PerformanceObserver 怎样接收长任务条目
页面出现点击迟钝、滚动卡顿时,我会先确认主线程是否出现了长任务,而不是直接把所有慢都归因于网络。浏览器把连续占用主线程 50 毫秒或更久的工作记录为 longtask 条目,前端可以用 PerformanceObserver 订阅它们。
官方资料地址:https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming
最小配方是new PerformanceObserver(callback)配合observer.observe({ type: 'longtask', buffered: true })。type指定单一条目类型,buffered让观察器接收建立之前已经被浏览器缓冲的条目;回调里再通过list.getEntries()批量处理。
longtask主要反映主线程连续忙碌达到 50ms 的任务,不能等同于完整的页面交互耗时。- 使用
buffered: true时要读取回调的第三个参数,留意droppedEntriesCount。 - 生产代码应先检查
PerformanceObserver.supportedEntryTypes,并在采集结束时调用disconnect()。
先确认 longtask 的观测边界
长任务是一个连续的主线程忙碌区间,常见来源包括很重的事件处理、昂贵的重排或重绘,以及一段没有主动让出主线程的 JavaScript。它适合回答“页面是否被一段连续工作卡住”,但不能直接告诉你某个函数就是唯一根因,也不能覆盖所有慢交互。
PerformanceLongTaskTiming 继承自 PerformanceEntry,常用字段是 startTime、duration、name 和 attribution。其中 duration 是条目持续时间,attribution 可能提供任务所在容器的信息。浏览器兼容性需要单独查看,不能因为 PerformanceObserver 本身普遍可用,就假定 longtask 在所有环境都存在。

用 type 与 buffered 建立观察器
observe() 有两种容易混淆的配置形态:entryTypes 用来观察多个类型,而 type 用来观察一个类型并配合 buffered。本题只接收 longtask,因此使用 type 更清楚,也避免把 buffered 和 entryTypes 放在一起。
const supported = PerformanceObserver.supportedEntryTypes ?? [];
if (supported.includes('longtask')) {
const observer = new PerformanceObserver((list, _observer, options) => {
// 一次回调可能包含多个条目,先批量取出再统一处理。
for (const entry of list.getEntries()) {
console.log({
type: entry.entryType,
duration: entry.duration,
startTime: entry.startTime,
name: entry.name,
});
}
// 缓冲区满时,记录丢失数量,避免把采样结果误认为完整数据。
if (options?.droppedEntriesCount > 0) {
console.warn('longtask 条目有丢失:', options.droppedEntriesCount);
}
});
// buffered 会把观察建立前已缓冲的 longtask 也交给回调。
observer.observe({ type: 'longtask', buffered: true });
// 页面或组件结束采集时调用 disconnect,停止继续接收条目。
window.addEventListener('pagehide', () => observer.disconnect(), { once: true });
}
这里的支持检测是一个分支,而不是对性能结果的判定:不支持时表示当前环境不能通过这条 API 获得数据,并不表示页面没有长任务。buffered 也不是“永久保存”,浏览器仍有缓冲容量限制。
从条目列表提取数据并控制上报量
观察器回调收到的是 PerformanceObserverEntryList,更适合在回调中完成轻量的归一化,然后把小批量结果交给上报队列。不要在每个条目回调里立即发一个网络请求,否则采集本身可能增加主线程和网络压力。
const pending = [];
function collectLongTasks(list) {
// 只保留上报需要的字段,避免把整条对象直接序列化。
for (const entry of list.getEntries()) {
pending.push({
duration: Math.round(entry.duration),
startTime: Math.round(entry.startTime),
container: entry.name,
attribution: entry.attribution?.map((item) => ({
// 归因字段可能随浏览器实现变化,缺失时保留 undefined。
containerId: item.containerId,
containerName: item.containerName,
containerSrc: item.containerSrc,
})),
});
}
}
const observer = new PerformanceObserver((list) => collectLongTasks(list));
observer.observe({ type: 'longtask', buffered: true });
function takeBatch() {
// 复制后清空本地队列,让下一轮采集不重复发送旧条目。
const batch = pending.splice(0, pending.length);
return batch;
}
attribution 适合做辅助线索,不能把它当作精确的函数调用栈。上报前还要按产品的隐私规则处理 containerSrc 等字段,并设置队列上限;本文只讨论如何接收条目,不把采集数据当作已完成的线上诊断。

调试检查清单:不生效时逐层排查
如果回调没有输出,我会按下面顺序排除,而不是先改阈值:
- 先看支持项:检查
PerformanceObserver.supportedEntryTypes是否包含longtask;不支持时记录能力差异,不能用空结果下结论。 - 再看订阅形态:确认使用的是
type: 'longtask',而不是把单类型写进entryTypes后又期待buffered生效。 - 再看时机:观察器越早建立,越容易接住后续条目;
buffered只能回放浏览器实际保留的条目。 - 最后看采集代码:确认没有过早调用
disconnect(),也不要在回调里执行重计算或同步大批量序列化。
还要留意 API 的边界:长任务以 50ms 为门槛,连续多个低于门槛的工作可能不会合并成一个 longtask;需要更细的渲染与脚本归因时,应另行评估 Long Animation Frames API,而不是把本文方案无限扩展。
常见问题
为什么 performance.getEntriesByType('longtask') 取不到数据?
部分条目类型不能通过通用的 getEntriesByType() 读取,长任务应使用 PerformanceObserver 订阅。
buffered: true 是不是能拿到页面从打开以来的全部长任务?
不是。它请求浏览器把已缓冲的匹配条目交给观察器,仍受浏览器缓冲容量和支持范围影响;回调中的 droppedEntriesCount 可以帮助发现缓冲丢失。
观察器应该什么时候断开?
组件销毁、页面离开或采集阶段结束时断开。持续监控则应保留观察器,但要让队列有上限,并把处理逻辑保持得足够轻。
前端 PerformanceResourceTiming 怎样定位资源响应时间
- 上一篇
- 前端 PerformanceResourceTiming 怎样定位资源响应时间
- 下一篇
- CSS container-type 怎样隔离组件查询范围
-
- 文章 · 前端 | 1小时前 | 并发控制 · 前端 Query Web Locks API LockManager 多标签页同步
- 前端 Web Locks 怎样查询当前持有者
- 284浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · javascript · JavaScript 国际化 语言边界 Intl.Segmenter 文本分词
- 前端 Intl.Segmenter 怎样按语言边界切分文本
- 432浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · 泛型 · typescript · TypeScript 泛型 keyof 对象键 属性读取
- TypeScript keyof 怎样约束对象键并安全读取属性
- 432浏览 收藏
-
- 文章 · 前端 | 1小时前 | ArrayBuffer structuredClone transfer
- 前端 structuredClone 怎样处理嵌套可转移对象
- 464浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · css · 深色模式 color-scheme light-dark CSS主题
- CSS light-dark 怎样为浅色深色主题切换颜色
- 379浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · css · CSS 组件布局 容器查询 container-type @container container-name
- CSS container-type 怎样隔离组件查询范围
- 295浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端性能 PerformanceResourceTiming 资源响应时间
- 前端 PerformanceResourceTiming 怎样定位资源响应时间
- 150浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- 前端 addEventListener 怎样用 once 自动移除一次性监听
- 204浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- 前端 ResizeObserver 怎样读取内容盒和边框盒尺寸
- 114浏览 收藏
-
- 文章 · 前端 | 1小时前 | 状态同步 BroadcastChannel 跨标签页
- 前端 BroadcastChannel 怎样同步不同标签页状态
- 306浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · javascript · 浏览器API · JavaScript 命名参数 前端路由 URLPattern pathname
- 前端 URLPattern 怎样按命名参数匹配路由路径
- 184浏览 收藏
-
- 文章 · 前端 | 1天前 | typescript ·
- TypeScript 怎样让索引访问显式处理 undefined
- 404浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 552次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 604次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 631次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 585次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 410次使用
-
- JavaScript函数定义及示例详解
- 2025-05-11 502浏览
-
- 智能体安全引领产业升级——国内AI安全产品市场深度分析
- 2026-08-21 501浏览
-
- CSS变量简化按钮悬停效果技巧
- 2026-05-31 501浏览
-
- JavaScript符号类型详解与应用
- 2026-05-31 501浏览
-
- HTML剪贴板复制粘贴怎么用
- 2026-05-26 501浏览

