前端监听错误
最近面试的时候遇到一个比较经典的问题,题目是这样的,在生产上,由于前端代码都是编译后的代码,那么发生生产错误的时候,前端如何监听错误的呢?又如何去找错误呢?我们本文就简单讲下这个问题
前端监听错误的方式
前端监听错误的方式可以分为三类,这里监听错误通常包含错误统计和上报
- JS 有4种方式
- vue 有2种方式
- react 有1种方式
JS
一、 try/catch
try/catch 主要是用来捕获代码常规的运行错误,不能捕捉语法错误和异步错误
1. 可以捕获常规运行的错误
try {
let a = undefined;
if (a.length) {
console.log('1111');
}
} catch (e) {
console.log('捕获到异常:',e);
}
2. 不能捕获语法错误
try {
const notdefined;
} catch (e) {
console.log('捕获不到异常:','Uncaught SyntaxError')
}
3. 不能捕获异步错误
try {
setTimeout(() => {
console.log(notdefined);
}, 0);
} catch (e) {
console.log('捕获不到异常:','Uncaught ReferenceError')
}
二、 window.onerror
window.onerror 可以捕获常规错误、异步错误,但不能捕获资源错误
window.onerror = function (message, source, lineno, colno, error) {
console.log("捕获到的错误信息是:", message, source, lineno, colno, error);
};
1. 可以捕获常规运行错误
console.log(notdefined);
2. 可以捕获异步错误
setTimeout(() => {
console.log(notdefined);
}, 0);
3. 不能捕获语法错误
const notdefined;
4. 不能捕获资源错误
let script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://www.test.com/index.js";
document.body.appendChild(script);
三、 window.addEventListener
当静态资源加载失败时,会触发 error 事件,此时 window.onerror 不能捕获到
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 图片、script、css加载错误,都能被捕获-->
<img src="https://test.cn/xxx.png">
<script src="https://test.cn/xxx.js"></script>
<link href="https://test.cn/xxx.css" rel="stylesheet" />
</body>
</html>
<script>
window.addEventListener('error',(error) => {
console.log('捕获到异常:',error);
},true)
</script>
四、Promise 错误
Promise中抛出的错误,无法被 window.onerror、try/catch、error 事件捕获到,可通过 unhandledrejection 事件来处理
// unhandledrejection 可以捕获Promise中的错误
window.addEventListener("unhandledrejection", function (e) {
console.log("捕获到异常", e);
// preventDefault阻止传播,不会在控制台打印
e.preventDefault();
});
vue
一、 vue 之 errorCaptured 生命周期
会监听所有下级组件的错误。可以返回 false 阻止向上传播,因为可能会有多个上级节点都监听错误。
function errorCaptured(error, instance, info) {
console.log("errorCaptured-------", error, instance, info);
}
二、 vue 之 errorHandler
全局的错误监听,所有组件的报错都会汇总到这里来。PS: 如果 errorCaptured 返回 false 则不会到这里,
请注意,errorHandler 会阻止错误走向 window,onerror(捕获常规错误)。即,常规错误到errorHandler就结束了,若是有异步错误仍会由onerror捕获
const app = createApp();
app.config.errorHandler = (error, instance, info) => {
console.log("errorHandler--------", error, instance, info);
};
react
一、react - ErrorBoundary
React + 引入。可以监听所有下级组件报错,同时降级展示 UI 。代码参考 ErrorBoundary.js 和 components/ErrorDemo 建议应用到最顶层,监听全局错误
// index.js 入口文件
ReactDOM.render(
<React.StrictMode>
<ErrorBoundary>
<App />
</ErrorBoundary>
</React.StrictMode>,
document.getElementById(" root"),
);
函数组件中也可以使用
function App(props) {
return <ErrorBoundary>{props.children}</ErrorBoundary>;
}