前端监听错误

383 阅读2分钟

前端监听错误

最近面试的时候遇到一个比较经典的问题,题目是这样的,在生产上,由于前端代码都是编译后的代码,那么发生生产错误的时候,前端如何监听错误的呢?又如何去找错误呢?我们本文就简单讲下这个问题

前端监听错误的方式

前端监听错误的方式可以分为三类,这里监听错误通常包含错误统计和上报

  • 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>

捕获异常-01.png

四、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>;
}