错误捕获

598 阅读4分钟

1.错误捕获

错误捕获是前端错误监控平台的关键步骤,通过捕获 JavaScript 运行时产生的错误,平台能够实时地感知到应用程序的健康状况。以下是错误捕获的主要内容:

全局错误事件监听

前端错误监控平台通常会注册全局的错误事件监听器,例如 window.onerror。这个事件在发生未被捕获的错误时触发,提供了一个机会来捕获错误并执行相应的处理逻辑。

window.onerror = function(message, source, lineno, colno, error) {
// 处理错误信息// 上报错误数据
};
 window.addEventListener("error", (event) => {
   console.error(`捕获到异常 window.error ==${event.type}: ${event.message}\n`, event);
 });

通过这个事件,平台可以捕获到错误的消息、发生错误的脚本文件、行号、列号以及错误对象本身。

对应参数:

ErrorEvent.prototype.message 只读

一个`字符串`,包含了所发生错误的描述信息。

ErrorEvent.prototype.filename 只读

一个 `字符串`,包含了发生错误的脚本文件的文件名。

ErrorEvent.prototype.lineno 只读

一个数字,包含了错误发生时所在的行号。

ErrorEvent.prototype.colno 只读

一个数字,包含了错误发生时所在的列号。

ErrorEvent.prototype.error 只读 实验性

发生错误时所抛出的 `Error` 对象。

错误类型

JavaScript 中常见的错误类型有多种,下面列举了一些主要的错误类型

  1. ReferenceError(引用错误):
window.onerror = function(message, source, lineno, colno, error) {
    console.error(`Error Type: ${error.name}`);
    console.error(`Error Message: ${error.message}`);
    console.error(`Source: ${source}`);
    console.error(`Line: ${lineno}`);
    console.error(`Column: ${colno}`);
};

function referenceErrorExample() {
    // 尝试访问未定义的变量
    console.log(undefinedVariable);
}

referenceErrorExample();
  1. TypeError(类型错误):
window.onerror = function(message, source, lineno, colno, error) {
    console.error(`Error Type: ${error.name}`);
    console.error(`Error Message: ${error.message}`);
    console.error(`Source: ${source}`);
    console.error(`Line: ${lineno}`);
    console.error(`Column: ${colno}`);
};

function typeErrorExample() {
    // 尝试对非函数类型的变量进行调用
    null();
}

typeErrorExample();
  1. SyntaxError(语法错误):
window.onerror = function(message, source, lineno, colno, error) {
    console.error(`Error Type: ${error.name}`);
    console.error(`Error Message: ${error.message}`);
    console.error(`Source: ${source}`);
    console.error(`Line: ${lineno}`);
    console.error(`Column: ${colno}`);
};

function syntaxErrorExample() {
    // 语法错误,如括号不匹配
    console.log('Hello World';
}

syntaxErrorExample();
  1. RangeError(范围错误):
window.onerror = function(message, source, lineno, colno, error) {
    console.error(`Error Type: ${error.name}`);
    console.error(`Error Message: ${error.message}`);
    console.error(`Source: ${source}`);
    console.error(`Line: ${lineno}`);
    console.error(`Column: ${colno}`);
};

function rangeErrorExample() {
    // 尝试传递超出范围的数值给函数
    const arr = new Array(-1);
}

rangeErrorExample();

这些示例展示了一些常见的错误类型,并通过 window.onerror 进行错误捕获。在实际应用中,为了更好地处理错误,通常会根据错误类型进行适当的处理和上报。

异步错误捕获

对于异步操作中的错误,例如 Promise 或者 setTimeout 中的错误,平台还需额外处理。一种常见的方式是通过 window.addEventListener 监听 unhandledrejection 事件。

   window.addEventListener('unhandledrejection', function(event) {
        // 处理异步错误信息// 上报错误数据
    });
    // 测试
   const test = new Promise((resove, reject) => {
      reject('test');
    });
    test.then();

这样,平台能够捕获到 Promise 中未被处理的错误。

网络状态监听

 // 监听网络在线事件
   window.addEventListener('online', function () {
     console.log('网络恢复连接');
   });

   // 监听网络离线事件
   window.addEventListener('offline', function () {
     console.error('捕获到异常 您的网络异常,offline');
   });

window.addEventListener

  1. 参数不同:这个事件处理函数的参数是一个 Event 对象,包含了 error 属性,它也是一个包含错误信息的对象。
  2. 错误捕获的范围: window.onerror 主要用于捕获全局的未被捕获的错误,包括运行时错误、语法错误、异步操作中的错误等。但是,它无法捕获某些类型的错误,比如资源加载错误(例如图片加载失败)。window.addEventListener('error') 可以用于捕获更多类型的错误,包括资源加载错误,如图片、脚本、样式表加载失败等
  3. 多个监听器的处理方式:window.onerror 只允许设置一个全局错误事件监听器。window.addEventListener('error') 允许注册多个错误事件监听器,它们将按照注册的顺序执行。
  4. 阻止默认行为的方式:window.onerror 回调函数可以返回 true 来阻止浏览器默认的错误处理行为。在 window.addEventListener('error', function(event) {}) 的回调函数中,可以调用 event.preventDefault() 来阻止浏览器默认的错误处理行为。
window.addEventListener('error', function(event) {
// 图片、script、css加载错误,都能被捕获
});

vue

在 Vue 中,你可以通过配置 errorHandler 来捕获全局的错误。Vue 提供了一个全局的错误处理器,可以用来捕获组件渲染和生命周期钩子中的错误。通过这个错误处理器,你可以自定义错误的处理方式,包括上报到错误监控平台。传入 Vue 实例是为了更好地融入 Vue 生态系统,方便获取当前组件的上下文信息。

下面是一个完整的 Vue 错误捕获的示例:

// main.js
import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false;

// 全局错误处理器
Vue.config.errorHandler = function(err, vm, info) {
    // err: 错误对象// vm: Vue 实例,发生错误的组件
    // info: Vue 特定的错误信息,比如错误所在的生命周期钩子
    // 在实际应用中,你可以将错误信息上报到错误监控平台c
    onsole.error('Vue Error:', err, info);
    // 如果需要阻止该错误继续传播,可以返回 false// return false;
};

new Vue({
    render: h => h(App),
}).$mount('#app');

React componentDidCatch

一般来说,它与 [static getDerivedStateFromError] 一起使用,这样做允许你更新 state 来响应错误并向用户显示错误消息。具有这些方法的组件称为 错误边界

class ErrorBoundary extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  // 捕获错误边界,render错误会执行
  componentDidCatch(error: any, errorInfo: any) {
    // Display fallback UI
    this.setState({
      hasError: true,
      error,
      errorInfo,
    });
    console.log('错误边界捕获:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
            <div style={{  padding: '20px' }}>
              {this.state.error && this.state.error.toString()}
              <br />
              {this.state.errorInfo.componentStack}
            </div>
      );
    }
    return this.props.children;
  }
}

2.错误信息采集

错误信息采集阶段是为了获取更多关于错误的上下文信息,以便更好地分析和解决问题。下面详细介绍错误信息采集的实现方法:

堆栈轨迹信息

通过错误对象的堆栈轨迹(stack trace),平台可以获取导致错误的函数调用链。这对于定位错误位置非常有帮助。

window.onerror = function(message, source, lineno, colno, error) {
    const stackTrace = error.stack;// 上报错误数据,包含堆栈轨迹信息
};

错误发生位置

window.onerror 事件中,source 参数提供了发生错误的脚本文件的 URL。结合行号和列号,可以准确地定位到错误发生的位置。

window.onerror = function(message, source, lineno, colno, error) {
    const errorLocation = `${source}:${lineno}:${colno}`;// 上报错误数据,包含错误发生位置信息
};

错误类型判断

错误对象中的 name 属性通常包含了错误的类型。通过判断错误类型,平台可以对错误进行分类,有针对性地进行处理。

window.onerror = function(message, source, lineno, colno, error) {
    const errorType = error.name;// 根据错误类型进行处理// 上报错误数据,包含错误类型信息
};

参考: developer.mozilla.org/en-US/docs/…

developer.mozilla.org/zh-CN/docs/…

juejin.cn/post/698768… www.cnblogs.com/beileixinqi…