易学社
第二套高阶模板 · 更大气的阅读体验

全局错误监听怎么实现 实用操作步骤与避坑指南

发布时间:2025-12-18 22:51:12 阅读:272 次

前端 JavaScript 的全局错误监听

在网页开发中,用户可能遇到脚本报错但开发者却毫不知情。为了及时捕获这些意外,全局错误监听就成了必不可少的一环。比如,用户点击按钮没反应,其实背后 JS 报了 TypeError,但页面没提示,问题就被忽略了。

在浏览器环境中,可以通过 window.onerror 捕获未捕获的运行时错误:

window.onerror = function(message, source, lineno, colno, error) {
console.log('全局错误:', { message, source, lineno, colno, error });
// 可以上报到日志服务器
reportErrorToServer({
type: 'js_error',
message,
stack: error?.stack,
url: source,
line: lineno,
column: colno
});
return true; // 阻止默认上报行为
};

这个方法能监听大部分同步错误,但对 Promise 异常无效。

监听 Promise 错误

如果项目中大量使用异步操作,Promise 被 reject 但没有 catch 时,window.onerror 是捕获不到的。这时候需要 unhandledrejection 事件:

window.addEventListener('unhandledrejection', function(event) {
console.log('未处理的 Promise 拒绝:', event.reason);
event.preventDefault(); // 防止控制台输出红色警告
reportErrorToServer({
type: 'promise_rejection',
reason: event.reason
});
});

Vue 和 React 中的错误处理

现代框架有自己的错误机制。比如 Vue 提供了 app.config.errorHandler,可以统一处理组件渲染和 watcher 错误:

const app = Vue.createApp({ ... });

app.config.errorHandler = (err, instance, info) => {
console.error('Vue 错误:', err, info);
reportErrorToServer({
type: 'vue_error',
error: err,
component: instance?.$options?.name,
info
});
};

React 则推荐使用 Error Boundary(错误边界),通过类组件的 componentDidCatch 捕获子组件的渲染错误:

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

componentDidCatch(error, info) {
console.error('React 错误边界捕获:', error, info);
reportErrorToServer({
type: 'react_error',
error,
componentStack: info.componentStack
});
this.setState({ hasError: true });
}

render() {
if (this.state.hasError) {
return <div>页面出错了</div>;
}
return this.props.children;
}
}

后端 Node.js 的全局异常监听

在服务端,Node.js 提供了类似的机制。比如监听未捕获的异常和 Promise 拒绝:

process.on('uncaughtException', (error) => {
console.error('未捕获异常:', error);
reportErrorToServer({
type: 'uncaughtException',
error: error.message,
stack: error.stack
});
// 注意:进程不会自动退出,建议退出重启
process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
reportErrorToServer({
type: 'unhandledRejection',
reason: reason?.message || reason,
promise
});
});

这类监听适合用在后台服务中,避免一次异常导致整个服务挂掉而无人知晓。

结合监控平台使用

实际项目中,可以把错误信息发送到专门的监控接口。比如自己搭一个 /api/report-error 接口接收数据,再聚合展示。也可以接入 Sentry、Bugsnag 这类工具,它们底层就是基于上述机制实现的。

上线前加一层全局监听,就像给车装上黑匣子。出了问题,不用靠用户描述“点了一下就没反应”,直接看日志就能定位。