前端错误分类

前端常见错误类型及其捕获方式

问题

前端错误有哪些分类?如何捕获这些错误?

解答

1. JavaScript 运行时错误

代码执行过程中抛出的错误,如类型错误、引用错误等。

// 常见运行时错误
const obj = null;
obj.name; // TypeError: Cannot read property 'name' of null

foo(); // ReferenceError: foo is not defined

// 捕获方式:try-catch
try {
  const obj = null;
  obj.name;
} catch (error) {
  console.log(error.name);    // TypeError
  console.log(error.message); // Cannot read property 'name' of null
}

// 全局捕获
window.onerror = function(message, source, lineno, colno, error) {
  console.log('捕获到错误:', { message, source, lineno, colno, error });
  return true; // 阻止默认处理
};

2. 语法错误

代码解析阶段的错误,无法被 try-catch 捕获。

// SyntaxError - 这类错误在解析阶段就会报错
// const a = ; // Unexpected token ';'

// 只能通过 eval 执行的代码才能被 try-catch 捕获
try {
  eval('const a = ;');
} catch (error) {
  console.log(error.name); // SyntaxError
}

3. 资源加载错误

图片、脚本、样式等资源加载失败。

// 方式一:元素的 onerror 事件
const img = new Image();
img.onerror = function(event) {
  console.log('图片加载失败');
};
img.src = 'not-exist.png';

// 方式二:全局捕获(需要在捕获阶段)
// 资源加载错误不会冒泡,必须用 capture: true
window.addEventListener('error', function(event) {
  const target = event.target;
  if (target !== window) {
    console.log('资源加载失败:', target.src || target.href);
  }
}, true); // 注意:第三个参数必须是 true

4. Promise 错误

未被 catch 处理的 Promise rejection。

// 未捕获的 Promise 错误
Promise.reject('出错了');

new Promise((resolve, reject) => {
  throw new Error('Promise 内部错误');
});

// 全局捕获
window.addEventListener('unhandledrejection', function(event) {
  console.log('未处理的 Promise 错误:', event.reason);
  event.preventDefault(); // 阻止默认处理(控制台报错)
});

5. 网络请求错误

Ajax、Fetch 请求失败。

// Fetch 错误处理
fetch('/api/data')
  .then(response => {
    // HTTP 错误状态不会触发 catch,需要手动判断
    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`);
    }
    return response.json();
  })
  .catch(error => {
    console.log('请求失败:', error.message);
  });

// XMLHttpRequest 错误处理
const xhr = new XMLHttpRequest();
xhr.onerror = function() {
  console.log('网络错误');
};
xhr.onload = function() {
  if (xhr.status >= 400) {
    console.log('HTTP 错误:', xhr.status);
  }
};

6. 跨域错误

Script Error,跨域脚本的错误信息被浏览器隐藏。

// 跨域脚本错误只会显示 "Script error.",没有详细信息

// 解决方案:
// 1. 脚本添加 crossorigin 属性
// <script src="https://other.com/app.js" crossorigin="anonymous"></script>

// 2. 服务器设置 CORS 头
// Access-Control-Allow-Origin: *

错误监控完整示例

// 统一错误上报函数
function reportError(type, error) {
  const data = {
    type,
    message: error.message || error,
    stack: error.stack,
    url: location.href,
    time: Date.now()
  };
  // 使用 sendBeacon 上报,不阻塞页面
  navigator.sendBeacon('/api/error', JSON.stringify(data));
}

// 1. JS 运行时错误
window.onerror = function(message, source, lineno, colno, error) {
  reportError('runtime', error || { message });
  return true;
};

// 2. 资源加载错误
window.addEventListener('error', function(event) {
  if (event.target !== window) {
    reportError('resource', { message: event.target.src || event.target.href });
  }
}, true);

// 3. Promise 错误
window.addEventListener('unhandledrejection', function(event) {
  reportError('promise', event.reason);
});

关键点

  • 运行时错误:用 try-catch 或 window.onerror 捕获
  • 资源加载错误:必须在捕获阶段监听(addEventListener 第三个参数为 true)
  • Promise 错误:用 unhandledrejection 事件捕获
  • 跨域脚本错误:需要 crossorigin 属性 + CORS 头才能获取详细信息
  • window.onerror 无法捕获:资源加载错误、Promise 错误、语法错误