1. 1. 错误分类
  2. 2. 捕获错误
    1. 2.1. 针对及时运行错误
    2. 2.2. 针对资源加载错误
    3. 2.3. 跨域的JS资源错误
  3. 3. 错误上报
    1. 3.1. 使用AJAX上报
    2. 3.2. 借助Image对象上报

产品上线前我们有各种手段来进行测试,确保产品质量可靠,达到可上线标准。但上线之后就真的没有问题了吗?真实情况大多是上线前各种测试没有任何问题,上线后用户反馈出了各种bug,而你根据反馈怎么整都复现不出来。崩溃不崩溃!!!

如何进行错误监控,就是这节要聊的主题,线上出现问题后,及时进行错误收集,bug分析。

错误分类

  • 及时运行错误 :即代码执行过程中的错误
  • 资源加载错误 :脚本加载失败,图片加载失败….;资源加载错误不冒泡

捕获错误

针对及时运行错误

  • try...catch看我这个介绍

  • window.onerron

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!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>
    window.onerror = e => {
    console.error('错误监控', e)
    }
    </script>
    </body>
    </html>

    注意这段用来监控执行过程中的错误的 JS 代码,需要写在其他 JS 引入的开头;

    且对于其他通过外链引入的JS文件,执行错误只能打印出 Script error. 无法打印出更多的错误信息。

针对资源加载错误

  • Error 事件捕获

    1
    2
    3
    window.addEventListener('error', e => {
    console.log('错误监听', e);
    }, true);

    我们通过 window.onerror 无法监听到资源加载错误,是因为 window.onerror 是在事件冒泡阶段执行的,而资源加载错误不冒泡,所以无法监听;

    但是通过 window.addEventListener('error', () => {}, true) 我们可以选择让监听在捕获阶段执行,自然就可以监听到了。

    如果在代码中进行了错误处理,没有将错误向外抛,那么无论怎样,也监听不到错误;例如:

    1
    2
    3
    try {} catch (err) {
    console.error(err);
    }

    你在控制台会看到报错,但你错误监控却没有执行。如果同时想要在错误监控中收集到,你需要将错误抛出去,上面的代码可以这样修改:

    1
    2
    3
    4
    try {} catch (err) {
    console.error(err);
    throw new Error(err);
    }
  • Object.onerror : 给资源加载添加 onerror 事件

    1
    2
    <img src="https://www.github.com/static/xxxxx.png" onerror="handleImgErr()" alt="" srcset="">
    <video src="https://www.gitee.com/staic/xxxx.mp4" onerror="handleVideoErr()"></video>
    1
    2
    3
    4
    5
    6
    const handleImgErr = e => {
    console.log('img加载错误.错误内容:', e);
    }
    const handleVideoErr = e => {
    console.log('video加载错误,错误内容:', e);
    }
  • performance.getEntries

    performance介绍看这里

    performance.getEntries介绍看这里

    getEntries() 可以拿到所有已经加载成功的资源,document.getElementsByTagName('有加载资源的标签') 可以拿到所有需要加载资源的标签,做个减法就可以得到那些资源没有加载成功。

    1
    2
    3
    4
    5
    // 以获取加载图片失败的数量为例
    const loadSucImgTotal = performance.getEntries().filter(item => item.initiatorType === 'img').length;
    const allLoadImgTotal = document.getElementsByTagName('img').length;

    const failImgTotal = allLoadImgTotal - loadSucImgTotal;

    performance.getEntries 确实可以间接的拿到资源加载的错误,但很明显,它只是解决问题的一种途径,但并不是特别好的途径

跨域的JS资源错误

对于不同源的JS资源,上面的代码可以监听到错误,但无法拿到错误内容

  • 错误提示

    image-20200212175525643

  • 解决方法

    1. script 标签增加crossorigin 属性
    2. 在设置JS资源响应Access-Control-Allow-Origin: *

错误上报

使用AJAX上报

借助Image对象上报

一行代码,借助Image 构造函数 生成一个image 对象,src 属性填写你上报错误的接口,直接发送请求上报错误。

1
(new Image()).src = '填写你上报错误的接口,参数拼后面'

重点:

很明显使用 **`Image`** 进行错误上报,简单又方便,所以不仅仅是应对面试,在真实的需要进行错误收集的场景中,第一选择也应该是 **`Image`**