前端错误监控

实际工作中,无论是开发环境还是生产环境都不可避免的会产生错误,快速的找出错误、上报错误、及时修复错误非常重要,能减小或避免重大损失和客户流失。保证上线的产品质量也是说的错误监控,因为产品上线后,线上的代码错误如果都不能收集的话,如何保证产品质量呢。

1. 错误分类

前端错误通常可以分为代码错误(即时运行错误)资源加载错误

1.1. 代码错误

可以使用以下方式来捕获错误。

  • try-catch-finally
  • window.onerror (或监听 window 的 error 事件)
  • unhandledrejection 属性可以监听没有被 catch 的 promise 错误信息。
  • Vue 框架可以使用 errorCaptured (生命周期钩子)监听下级组件报错,返回 false 阻止向上传播。
  • Vue 框架可以使用 errorHandler 监听全局 Vue 组件报错。指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。
  1. try-catch-finally

这种方法只是适用于在风险比较高的地方捕获,因为很多地方都这样写成本太高。

try {
    // 这里可能会产生错误
} catch(err) {
    // err 接收到 try 块儿中的错误
} finally {
    // TODO
}
  1. window.onerror

这种方法是一种全局的方法,能够捕获到大部分代码错误的场景。

window.onerror = function(message, source, colNum, rowNum, error) {
    // 对于外部 JS ,如加载的 CDN ,则无法清楚知道哪里报错
    // 对于线上被压缩过后的代码,也知不知道 colNum, rowNum,需要配合 sourcemap 来看。
}
  1. unhandledrejection

对于没有被 catch 的 promise 错误信息(异步错误),可以使用 window 监听 unhandledrejection 事件。

window.addEventListener('unhandledrejection', (error) => {
  console.error('捕获到异步异常', error);
});
  1. errorCaptured

errorCaptured

在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

(err: Error, vm: Component, info: string) => ?boolean
  1. errorHandler

errorHandler 指定一个处理函数,来处理组件渲染函数和侦听器执行期间抛出的未捕获错误。这个处理函数被调用时,可获取错误信息和相应的应用实例。

app.config.errorHandler = (err, vm, info) => {
  // 处理错误
  // `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
}

1.2. 资源加载错误

比如 CSS 、JS 、图片加载错误,可以使用以下方式来捕获错误。

  1. 对象的 onerror 方法

对象的 onerror 方法来捕获错误,比如图片 image.onerror。

function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = document.createElement("img");
    img.alt = "promise方式加载的图片";
    img.src = src;
    img.onload = () => {
      resolve(img);
    };
    img.onerror = () => {
      const err = new Error("图片加载失败!");
      reject(err);
    };
  });
}
  1. performance.getEntries()

根据发起的请求个数和成功的个数的一个比较,得出哪个请求出错了。

// 获取加载的资源的名称
// performance.getEntries() 返回一个数组
performance.getEntries().forEach(item => console.log(item.name))

上面代码返回成功加载的资源的名称,在和 network 面板请求的所有资源做一个对比,就能得出哪个(些)资源加载出错了。

  1. 捕获阶段监听 window 的 error 事件

资源加载错误,不会冒泡,所以无法直接通过 window.onerror 来捕获,但是可以通过监听 error 事件在捕获阶段来捕获。

window.onerror 只能捕获即时运行错误,对于资源运行错误没法捕获。

// 捕获阶段监听 error 事件
// 错误监控代码写在加载错误资源的前面
<script>
    window.addEventListener("error", function(event) {
        console.log("捕获资源加载错误", event);
    }, true); // 第三个参数为 true 表示捕获阶段
</script>
<script src="https://www.baidu.com/xcvbnmkjhgf.html"></script> // 模拟一个没有的地址,模拟资源加载错误

捕获资源家在错误

2. 跨域的资源如何监控

上面介绍代码错误使用 window.onerror 来捕获时,如果是跨域的就没法知道错误的行号和列号,对代码错误的排查没有帮助,这时候就需要服务端配合了。

  1. 客户端加上 crossorigin
  2. 服务端响应头加上 Access-Control-Allow-Origin: *

加上上面两步处理后,就可以拿到跨域错误的代码的详细信息了。

3. 上报错误的基本原理或方法

  • 通过 Image 对象上报, (new Image()).src='xxxxxx',最简单也不需要借助第三方库。
  • 通过 AJAX 通信上报。需要借助第三方库,比如 axios。

因为给 Image 对象附上 src 属性后,就会向服务器发送请求。这个时候 src 中可以携带我们需要上报的错误信息作为 search 部分传给服务端。

posted @ 2022-05-01 16:47  艾前端  阅读(542)  评论(0编辑  收藏  举报