Skip to content

前端错误捕获

约 1251 字大约 4 分钟

2025-02-20

在前端开发中,捕获错误是保证应用稳定性和用户体验的关键。为了全面捕获前端的错误,我们需要覆盖多种错误类型,并采用多种捕获机制。以下是全面捕获前端错误的策略和实现方法。

1. 错误类型

前端错误主要分为以下几类:

  1. JavaScript 运行时错误:
  • 语法错误、类型错误、引用错误等。
  1. 资源加载错误:
  • 图片、脚本、样式等资源加载失败。
  1. Promise 未捕获错误:
  • Promise 的 reject 未被捕获。
  1. 异步代码错误:
  • setTimeout、setInterval、requestAnimationFrame 等异步代码中的错误。
  1. 跨域脚本错误:
  • 跨域脚本中的错误(通常无法直接捕获,需要特殊处理)。
  1. 框架或库的错误:
  • Vue、React 等框架中的错误。
  1. 用户行为错误:
  • 用户操作导致的错误(如输入不合法)。

2. 错误捕获机制

  1. 全局错误捕获 使用 window.onerror 捕获全局 JavaScript 运行时错误。

window.onerror = function (message, source, lineno, colno, error) {
  console.error('全局错误:', { message, source, lineno, colno, error });
  // 将错误信息上报到服务器
  reportErrorToServer({ message, source, lineno, colno, error });
  return true; // 阻止默认错误处理
};
  1. 资源加载错误捕获 使用 window.addEventListener('error') 捕获资源加载错误。

window.addEventListener('error', function (event) {
  if (event.target && (event.target.tagName === 'IMG' || event.target.tagName === 'SCRIPT' || event.target.tagName === 'LINK')) {
    console.error('资源加载错误:', event.target.src || event.target.href);
    // 将错误信息上报到服务器
    reportErrorToServer({ type: 'resource', url: event.target.src || event.target.href });
  }
}, true); // 使用捕获模式
  1. Promise 未捕获错误 使用 window.onunhandledrejection 捕获未处理的 Promise 错误。

window.onunhandledrejection = function (event) {
  console.error('未捕获的 Promise 错误:', event.reason);
  // 将错误信息上报到服务器
  reportErrorToServer({ type: 'promise', reason: event.reason });
};
  1. 框架错误捕获 对于 Vue、React 等框架,可以使用框架提供的错误捕获机制。

Vue 2:


Vue.config.errorHandler = function (err, vm, info) {
  console.error('Vue 错误:', err, info);
  // 将错误信息上报到服务器
  reportErrorToServer({ type: 'vue', err, info });
};

React:


class ErrorBoundary extends React.Component {
  componentDidCatch(error, info) {
    console.error('React 错误:', error, info);
    // 将错误信息上报到服务器
    reportErrorToServer({ type: 'react', error, info });
  }

  render() {
    return this.props.children;
  }
}


// 使用 ErrorBoundary 包裹组件
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>
  1. 异步代码错误捕获 对于 setTimeout、setInterval 等异步代码,可以使用 try-catch 捕获错误。

function runAsyncCode(callback) {
  try {
    callback();
  } catch (error) {
    console.error('异步代码错误:', error);
    // 将错误信息上报到服务器
    reportErrorToServer({ type: 'async', error });
  }
}

setTimeout(() => runAsyncCode(() => {
  throw new Error('异步错误');
}), 1000);
  1. 跨域脚本错误捕获 跨域脚本错误通常无法直接捕获,但可以通过以下方式间接捕获:

使用 try-catch 包裹跨域脚本的执行。

在跨域脚本中手动捕获错误并通知主页面。

3. 错误上报

捕获错误后,需要将错误信息上报到服务器,以便分析和修复。常见的上报方式包括:

  1. 使用 XMLHttpRequest 或 fetch

function reportErrorToServer(error) {
  const url = 'https://your-server.com/log-error';
  const data = JSON.stringify(error);

  fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: data,
  }).catch((err) => {
    console.error('上报错误失败:', err);
  });
}
  1. 使用第三方错误监控服务
  • Sentry:https://sentry.io/

  • Bugsnag:https://www.bugsnag.com/

  • LogRocket:https://logrocket.com/

这些服务提供了完整的错误监控和上报功能,可以快速集成到项目中。

4. 错误处理的最佳实践

  1. 分类处理错误:
  • 根据错误类型(如运行时错误、资源加载错误等)进行分类处理。
  1. 避免阻塞主线程:
  • 错误捕获和上报逻辑应尽量轻量,避免阻塞主线程。
  1. 用户友好提示:
  • 对于用户可见的错误(如表单验证失败),提供友好的提示信息。
  1. 日志分级:
  • 根据错误的严重程度(如警告、错误、致命错误)进行分级处理。
  1. 定期分析错误日志:
  • 定期分析错误日志,发现和修复高频错误。

5. 完整示例

以下是一个完整的错误捕获和上报示例:


// 全局错误捕获
window.onerror = function (message, source, lineno, colno, error) {
  console.error('全局错误:', { message, source, lineno, colno, error });
  reportErrorToServer({ type: 'global', message, source, lineno, colno, error });
  return true;
};

// 资源加载错误捕获
window.addEventListener('error', function (event) {
  if (event.target && (event.target.tagName === 'IMG' || event.target.tagName === 'SCRIPT' || event.target.tagName === 'LINK')) {
    console.error('资源加载错误:', event.target.src || event.target.href);
    reportErrorToServer({ type: 'resource', url: event.target.src || event.target.href });
  }
}, true);

// Promise 未捕获错误
window.onunhandledrejection = function (event) {
  console.error('未捕获的 Promise 错误:', event.reason);
  reportErrorToServer({ type: 'promise', reason: event.reason });
};

// Vue 错误捕获
Vue.config.errorHandler = function (err, vm, info) {
  console.error('Vue 错误:', err, info);
  reportErrorToServer({ type: 'vue', err, info });
};

// 上报错误到服务器
function reportErrorToServer(error) {
  const url = 'https://your-server.com/log-error';
  const data = JSON.stringify(error);

  fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: data,
  }).catch((err) => {
    console.error('上报错误失败:', err);
  });
}

6. 总结

通过全局错误捕获、资源加载错误捕获、Promise 错误捕获、框架错误捕获等多种机制,可以全面捕获前端的错误。捕获错误后,及时上报并分析错误日志,是保证应用稳定性和用户体验的关键。希望这个指南能帮助你更好地处理前端错误!

© 2024 图图 📧 email