监听错误的方式有哪些?
| 建议 | 说明 |
|---|---|
✅ 同步代码用 try-catch | 基础必备 |
✅ Promise 一定要写 .catch() 或监听 unhandledrejection | 避免控制台报未处理的 rejection |
✅ 监听全局错误:window.addEventListener('error') 和 unhandledrejection | 兜底所有全局异常 |
| ✅ React 项目使用 Error Boundary | 捕获组件渲染错误 |
✅ Vue 项目使用 errorHandler | 捕获 Vue 组件错误 |
| ✅ 生产环境接入错误监控平台(如 Sentry) | 实时发现、定位、修复线上问题 |
📩 如果你有具体场景,比如:
在 JavaScript 中,不是所有错误都能用
try-catch直接捕获(比如异步代码中的错误、Promise 未处理的 rejection、全局脚本错误、资源加载错误等),要全面监听错误,我们需要使用多种方式,包括:try-catch(同步)、catch(Promise)、window.onerror、window.addEventListener('error')、window.addEventListener('unhandledrejection')、框架提供的错误边界(如 React Error Boundary)、以及全局异常监控等。
try-catch 捕获不到的用什么方法
| 场景 | 能否用 try-catch 捕获 | 原因 |
|---|---|---|
| **同步代码抛出的错误(如 throw new Error)** | ✅ 能 | 常规用法,包围可能出错的代码块 |
| 异步代码(如 setTimeout、事件回调)中抛出的错误 | ❌ 不能 | try-catch 无法跨越异步边界捕获 |
**未被捕获的 Promise 错误(如 Promise 内部 throw 或 reject 但没 .catch())** | ❌ 不能 | 需要通过 catch() 或监听 unhandledrejection 事件 |
| **全局脚本错误(如引入的第三方 JS 报错)** | ❌ 不能 | 需要监听 window.onerror 或 error 事件 |
| **资源加载错误(如图片、脚本、CSS 加载失败)** | ❌ 不能 | 需要监听 error 事件(如 <img onerror> 或全局监听) |
✅ 监听与捕获错误的主要方式(全面总结)
✅ 1. 同步代码:使用 try-catch(最基础)
适用于同步代码中可能抛出异常的地方,比如:
try {// 可能抛出错误的同步代码throw new Error('同步错误');
} catch (error) {console.error('捕获到同步错误:', error.message);
}
✅ **能捕获:** 同步代码中通过 throw 抛出的错误
❌ **不能捕获:** 异步代码、Promise 错误、全局错误等
✅ 2. 异步代码(Promise):使用 .catch() 捕获
如果使用 Promise,一定要记得添加 .catch(),否则未捕获的 Promise 会成为全局未处理的 rejection。
someAsyncFunction().then(data => {console.log(data);}).catch(error => {console.error('捕获到 Promise 错误:', error);});
✅ **能捕获:** Promise 链中发生的错误
❌ **不能捕获:** 如果没有写 .catch(),错误会变成 未处理的 rejection
✅ 3. 监听未被捕获的 Promise 错误:window.addEventListener('unhandledrejection')
当有 Promise 被 reject 但未被 .catch() 捕获 时,会触发此事件。
window.addEventListener('unhandledrejection', event => {console.error('捕获到未处理的 Promise 错误:', event.reason);// 可以在这里上报错误// event.preventDefault(); // 可选:阻止默认控制台报错
});
✅ **用途:** 兜底捕获所有未处理的 Promise 错误,避免控制台报未处理的 rejection
🔒 **最佳实践:** 一定要监听,用于全局兜底和错误上报
✅ 4. 监听全局 JavaScript 错误:window.onerror 或 window.addEventListener('error')
用于捕获:
- ∙同步代码中未被
try-catch捕获的错误 - ∙全局脚本(比如引入的第三方库)抛出的错误
- ∙但 无法捕获异步代码(如 setTimeout)里的错误!
方法 1:window.onerror(简单全局错误监听)
window.onerror = function (message, source, lineno, colno, error) {console.error('全局错误:', message, '发生在', source, '行号:', lineno);return true; // 返回 true 可阻止错误继续向上抛出(阻止控制台报错)
};
方法 2:window.addEventListener('error')(更推荐,更灵活)
window.addEventListener('error', event => {console.error('全局错误事件:', event.error);// event.filename, event.lineno, event.colno, event.message
});
✅ **能捕获:** 大部分同步全局错误、脚本加载错误
❌ **不能捕获:** Promise 错误、异步代码中通过 setTimeout 抛出的错误
✅ 5. 监听资源加载错误(如图片、脚本、样式等)
比如图片加载失败,可以通过 onerror 监听:
<img src="wrong-path.jpg" alt="图片" onerror="console.error('图片加载失败')" />
或者全局监听资源加载错误(通过 error 事件冒泡,但注意限制较多,通常要针对具体元素监听)
✅ 6. React 中的错误边界(Error Boundary)—— 组件级错误监听
React 提供了 **错误边界(Error Boundaries)** 这一机制,只能捕获子组件树中的渲染时错误(不是所有错误!),不能捕获事件处理器、异步代码中的错误。
用法:
class ErrorBoundary extends React.Component {constructor(props) {super(props);this.state = { hasError: false };}static getDerivedStateFromError(error) {return { hasError: true };}componentDidCatch(error, info) {console.error('组件渲染出错:', error, info);// 可以上报错误到服务}render() {if (this.state.hasError) {return <h1>出现了错误,请刷新页面</h1>;}return this.props.children;}
}// 使用方式
<ErrorBoundary><MyComponent />
</ErrorBoundary>
✅ **能捕获:** React 组件渲染过程中抛出的错误(仅 Class 组件可以做 Error Boundary)
❌ **不能捕获:** 函数组件、事件处理函数、异步代码中的错误
✅ 7. 全局错误上报(接入 Sentry、Fundebug、自建服务等)
无论你通过哪种方式监听到错误,最佳实践都是:
将错误信息收集并上报到错误监控平台,如:
- ∙Sentry(强烈推荐)
- ∙Fundebug
- ∙自建日志服务
上报内容通常包括:
- ∙错误信息(message、stack)
- ∙用户信息、设备信息、页面 URL
- ∙发生时间、环境信息等
