ReportingObserver 是浏览器原生 API,用于监听 CSP 违规、deprecation、intervention、crash 等运行时报告,不捕获 JS 错误或网络失败;需早期注册、指定 types 并调用 observe(),且依赖浏览器支持与服务端配置。

ReportingObserver 是什么,它能捕获哪些报告
ReportingObserver 是浏览器原生提供的 API,用于监听和收集由浏览器主动发出的各类运行时报告(reports),比如 CSP 违规、deprecation 警告、intervention 干预行为等。它不捕获 JavaScript 错误(那是 window.onerror 或 addEventListener('error') 的事),也不捕获网络请求失败(那是 PerformanceObserver 或 Navigation Timing 的范畴)。
它只响应那些浏览器明确通过 ReportBody 格式发出的报告,常见类型包括:
"csp-violation""deprecation""intervention"-
"crash"(部分浏览器支持)
注意:不是所有报告类型在所有浏览器都可用;"deprecation" 在 Chrome 93+ 默认启用,但需确保 DevTools 控制台未关闭相关日志开关,否则可能“看不见”。
如何创建并启用 ReportingObserver 实例
创建实例很简单,但关键在参数和时机:
立即学习“前端免费学习笔记(深入)”;
- 必须在页面加载早期注册(最好在
<head>中或 DOMContentLoaded 前),否则会错过初始报告 - 构造函数第二个参数是配置对象,其中
types是必填数组,指定监听的报告类型 -
buffered设为true可捕获注册前已生成的报告(仅对部分类型有效,如deprecation在 Chrome 中支持)
<script>
const observer = new ReportingObserver((reports, observer) => {
reports.forEach(report => {
console.log('捕获到报告:', report.type, report.body);
});
}, {
types: ['deprecation', 'intervention'],
buffered: true
});
<p>observer.observe();
</script></p>别忘了调用 observe() —— 这步容易遗漏,不调用就不会开始监听。
为什么有些报告始终收不到
常见原因不是代码写错,而是环境或配置限制:
-
CSP报告需要服务端配合:必须设置Content-Security-Policy-Report-Only响应头,并指定report-toendpoint,且该 endpoint 需提前通过Reporting-Endpoints响应头声明,否则浏览器不会发送报告,ReportingObserver自然无从监听 -
deprecation报告默认只在开发者工具打开时触发(Chrome 行为),关掉 DevTools 后很多弃用警告就静默了;可通过启动 Chrome 时加--enable-blink-features=DeprecationReporting强制启用(仅限本地调试) -
intervention类型在某些版本中被重命名为"coep-preloaded-response"等更具体的类型,建议用console.log(reports)打印原始报告看实际type字段值 - Safari 和 Firefox 当前(2024)基本不支持
ReportingObserver,不要依赖它做跨浏览器兼容性兜底
如何把捕获的报告发给后端
ReportingObserver 本身不上传数据,需手动发送。注意两点:
- 报告体(
report.body)是普通 JS 对象,可直接JSON.stringify,但部分字段(如url、lineNumber)可能为undefined,需容错处理 - 推荐用
sendBeacon()发送,避免页面卸载时丢失(fetch在beforeunload中可能被中断)
const observer = new ReportingObserver(reports => {
const payloads = reports.map(r => ({
type: r.type,
body: r.body,
timestamp: Date.now()
}));
<p>navigator.sendBeacon('/api/report', JSON.stringify(payloads));
});</p>sendBeacon() 的 payload 必须是 Blob、ArrayBuffer 或字符串;传对象会报错,记得 JSON.stringify。
CSP 报告体积可能较大,sendBeacon 有约 64KB 限制,超限时需截断或降级用 fetch + keepalive: true(但兼容性稍差)。
真正难的不是监听,是让浏览器愿意发报告——这取决于你的 CSP 头、是否开着 DevTools、用的是哪个浏览器,以及有没有提前声明 endpoint。漏掉任一环,ReportingObserver 就只是个安静的空壳。



















