前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK
在讲错误收集方式之前,先理清一下前端编码时有那些常见错误
前端错误收集是保障用户体验、排查线上问题的关键手段。本文将从多个角度详解前端错误收集的各种方式,包括不同框架(如 React、Vue)、JavaScript 执行环境中的同步/异步/Promise 错误、资源加载错误(如图片、script 加载失败)等。以下是全面的错误捕获机制总结:
🌐 一、通用错误收集方式(原生 JavaScript)
1. try...catch 捕获同步代码错误
try { // 同步代码 let result = a.b; // 触发错误 } catch (err) { console.error('捕获同步错误:', err); }
注意:
- 只能捕获同步代码错误,不能捕获异步或事件回调内的错误。
2. window.onerror
window.onerror = function (message, source, lineno, colno, error) { console.error('window.onerror 捕获:', { message, source, lineno, colno, error }); };
特性:
- 可捕获运行时错误,包括未捕获的异常。
- 跨域脚本错误默认不会暴露具体信息,需设置 crossorigin 属性和响应头。
3. window.addEventListener('error') 捕获资源加载错误
window.addEventListener('error', function (event) { if (event.target instanceof HTMLScriptElement || event.target instanceof HTMLImageElement) { console.error('资源加载错误:', event.target.src || event.target.href); } else { console.error('运行时错误:', event.message); } }, true); // 第三个参数为 true 表示捕获捕获阶段的错误
优点:
- 能捕获
, , 等静态资源加载错误。
4. unhandledrejection 捕获未处理的 Promise 异常
window.addEventListener('unhandledrejection', function (event) { console.error('未处理的 Promise 异常:', event.reason); });
场景:
- Promise 的 .catch() 未添加或写在不合适位置。
⚛️ 二、React 中的错误捕获
1. React 16+ 错误边界(Error Boundaries)
class ErrorBoundary extends React.Component { state = { hasError: false, error: null }; static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { console.error('React 错误捕获:', error, info); } render() { if (this.state.hasError) { return
出错了
; } return this.props.children; } }限制:
-
只能捕获子组件生命周期、render、构造函数中的错误。
-
不能捕获:
- 异步代码(如 setTimeout)
- 事件处理函数错误
- SSR 期间的错误
🐸 三、Vue 中的错误捕获
1. Vue 2.x errorHandler
Vue.config.errorHandler = function (err, vm, info) { console.error('Vue 错误:', err, info); };
2. Vue 3.x app.config.errorHandler
const app = Vue.createApp(App); app.config.errorHandler = (err, instance, info) => { console.error('Vue3 错误:', err, info); };
3. 异步函数中的错误
异步函数内的错误需要使用 try/catch 或监听 unhandledrejection。
🧠 四、异步任务中的错误处理方式
1. setTimeout、setInterval
setTimeout(() => { try { throw new Error('异步定时错误'); } catch (err) { console.error('捕获异步错误:', err); } }, 1000);
2. Promise 中的异常
new Promise((resolve, reject) => { throw new Error('Promise 内部异常'); // 会触发 unhandledrejection });
3. async/await 异常处理
async function test() { try { await fetch('...'); throw new Error('异步错误'); } catch (e) { console.error('async/await 错误:', e); } }
🖼️ 五、资源加载错误(图片、脚本等)
图片加载失败
脚本加载失败
全局监听
window.addEventListener('error', function (e) { if (e.target.tagName === 'IMG' || e.target.tagName === 'SCRIPT') { console.error('资源加载失败:', e.target.src || e.target.href); } }, true);
📦 六、前端错误上报实践建议
-
统一封装错误上报工具
function reportError(errorInfo) { // 上报至日志平台 fetch('/log', { method: 'POST', body: JSON.stringify(errorInfo), }); }
-
错误去重、限频
- 防止相同错误反复上报。
-
结合 Source Map
- 错误行号定位需要 source map 还原。
-
配合监控平台(如 Sentry、Fundebug、LogRocket)
- 可视化查看错误堆栈、用户行为路径等。
✅ 总结
类型 捕获方式 说明 同步代码异常 try...catch 推荐搭配日志上报使用 全局 JS 错误 window.onerror 支持堆栈、来源信息 静态资源加载失败 window.addEventListener('error', ..., true) 捕获 / / 加载失败
Promise 未处理异常 window.unhandledrejection 捕获 Promise 中未被 .catch 处理的异常 React 错误边界组件 捕获渲染和生命周期异常 Vue config.errorHandler 支持全局组件异常处理 async/await 异常 try/catch 手动捕获为主 如需我帮你生成一个完整的错误收集 SDK、结合你项目的架构,欢迎告诉我。
下面是一个通用的前端错误收集 SDK,适用于纯 JavaScript 应用,也兼容 React、Vue 等框架。具备如下能力:
- 捕获同步错误(try/catch)
- 捕获未处理的 Promise 错误
- 捕获资源加载失败(如图片、脚本)
- 可扩展支持自定义上报方式
- 可用于构建自己的埋点/监控平台
✅ 错误收集 SDK 示例(error-tracker.js)
class ErrorTracker { constructor(options = {}) { this.reportUrl = options.reportUrl || '/report-error'; this.extraContext = options.context || {}; this.init(); } init() { this.bindGlobalError(); this.bindPromiseRejection(); this.bindResourceError(); } bindGlobalError() { window.onerror = (message, source, lineno, colno, error) => { const errorInfo = { type: 'js-error', message, source, lineno, colno, stack: error?.stack, ...this.extraContext, }; this.report(errorInfo); }; } bindPromiseRejection() { window.addEventListener('unhandledrejection', (event) => { const errorInfo = { type: 'unhandledrejection', reason: event.reason?.message || String(event.reason), stack: event.reason?.stack || null, ...this.extraContext, }; this.report(errorInfo); }); } bindResourceError() { window.addEventListener( 'error', (event) => { if (event.target && (event.target.src || event.target.href)) { const errorInfo = { type: 'resource-error', tagName: event.target.tagName, url: event.target.src || event.target.href, outerHTML: event.target.outerHTML, ...this.extraContext, }; this.report(errorInfo); } }, true // 捕获资源加载错误必须设置为 true ); } report(errorData) { try { navigator.sendBeacon ? navigator.sendBeacon(this.reportUrl, JSON.stringify(errorData)) : fetch(this.reportUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(errorData), }); } catch (err) { console.warn('错误上报失败:', err); } } // 可手动上报 captureException(error, context = {}) { const errorInfo = { type: 'manual-capture', message: error.message, stack: error.stack, ...this.extraContext, ...context, }; this.report(errorInfo); } } export default ErrorTracker;
🧪 使用方法
1. 初始化
import ErrorTracker from './error-tracker'; const tracker = new ErrorTracker({ reportUrl: 'https://your-domain.com/log-collector', context: { appVersion: '1.0.0', userId: '123456', }, });
2. 手动捕获异常(适用于 try/catch 或自定义埋点)
try { throw new Error('业务异常'); } catch (e) { tracker.captureException(e, { module: 'UserProfile' }); }
🛠️ 后端上报接口示例(Node.js)
// express app.post('/report-error', express.json(), (req, res) => { console.log('错误上报:', req.body); // 可写入数据库、日志文件或推送到告警系统 res.status(200).send('ok'); });
💡 可扩展建议
- 加入节流、去重机制(防止重复错误刷爆接口)
- 支持用户行为轨迹记录(如点击、页面跳转)
- 上报前过滤第三方脚本错误
- 使用 Source Map 解码堆栈信息
如果你希望我帮你生成一个适配你项目的版本(如适配 Vue3 或 React + Vite 项目,或打包成 NPM 包),告诉我你的技术栈,我可以继续完善。
-
-
- Promise 的 .catch() 未添加或写在不合适位置。
- 能捕获
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。