前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK

06-01 1154阅读

在讲错误收集方式之前,先理清一下前端编码时有那些常见错误

前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK

前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK


前端错误收集是保障用户体验、排查线上问题的关键手段。本文将从多个角度详解前端错误收集的各种方式,包括不同框架(如 React、Vue)、JavaScript 执行环境中的同步/异步/Promise 错误、资源加载错误(如图片、script 加载失败)等。以下是全面的错误捕获机制总结:


前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK

🌐 一、通用错误收集方式(原生 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);
                }
              }
              

              🖼️ 五、资源加载错误(图片、脚本等)

              图片加载失败

              前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK

              脚本加载失败

               
              

              全局监听

              window.addEventListener('error', function (e) {
                if (e.target.tagName === 'IMG' || e.target.tagName === 'SCRIPT') {
                  console.error('资源加载失败:', e.target.src || e.target.href);
                }
              }, true);
              

              前端错误收集方式(try...catch、window.onerror 、window.addEventListener(‘error‘)、unhandledrejection) 与通用的 SDK


              📦 六、前端错误上报实践建议

              1. 统一封装错误上报工具

                function reportError(errorInfo) {
                  // 上报至日志平台
                  fetch('/log', {
                    method: 'POST',
                    body: JSON.stringify(errorInfo),
                  });
                }
                
              2. 错误去重、限频

                • 防止相同错误反复上报。
                • 结合 Source Map

                  • 错误行号定位需要 source map 还原。
                  • 配合监控平台(如 Sentry、Fundebug、LogRocket)

                    • 可视化查看错误堆栈、用户行为路径等。

              ✅ 总结

              类型捕获方式说明
              同步代码异常try...catch推荐搭配日志上报使用
              全局 JS 错误window.onerror支持堆栈、来源信息
              静态资源加载失败window.addEventListener('error', ..., true)捕获 // 加载失败
              Promise 未处理异常window.unhandledrejection捕获 Promise 中未被 .catch 处理的异常
              React错误边界组件捕获渲染和生命周期异常
              Vueconfig.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 包),告诉我你的技术栈,我可以继续完善。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码