产品上线前我们有各种手段来进行测试,确保产品质量可靠,达到可上线标准。但上线之后就真的没有问题了吗?真实情况大多是上线前各种测试没有任何问题,上线后用户反馈出了各种bug,而你根据反馈怎么整都复现不出来。崩溃不崩溃!!!
如何进行错误监控,就是这节要聊的主题,线上出现问题后,及时进行错误收集,bug分析。
错误分类
- 及时运行错误 :即代码执行过程中的错误
- 资源加载错误 :脚本加载失败,图片加载失败….;资源加载错误不冒泡
捕获错误
针对及时运行错误
window.onerron
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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
3window.addEventListener('error', e => {
console.log('错误监听', e);
}, true);我们通过
window.onerror
无法监听到资源加载错误,是因为window.onerror
是在事件冒泡阶段执行的,而资源加载错误不冒泡,所以无法监听;但是通过
window.addEventListener('error', () => {}, true)
我们可以选择让监听在捕获阶段执行,自然就可以监听到了。如果在代码中进行了错误处理,没有将错误向外抛,那么无论怎样,也监听不到错误;例如:
1
2
3try {} catch (err) {
console.error(err);
}你在控制台会看到报错,但你错误监控却没有执行。如果同时想要在错误监控中收集到,你需要将错误抛出去,上面的代码可以这样修改:
1
2
3
4try {} 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
6const handleImgErr = e => {
console.log('img加载错误.错误内容:', e);
}
const handleVideoErr = e => {
console.log('video加载错误,错误内容:', e);
}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资源,上面的代码可以监听到错误,但无法拿到错误内容
错误提示
解决方法
- 在
script
标签增加crossorigin
属性 - 在设置JS资源响应
Access-Control-Allow-Origin: *
- 在
错误上报
使用AJAX上报
借助Image对象上报
一行代码,借助Image
构造函数 生成一个image
对象,src
属性填写你上报错误的接口,直接发送请求上报错误。
1 | (new Image()).src = '填写你上报错误的接口,参数拼后面' |
重点:
很明显使用 **`Image`** 进行错误上报,简单又方便,所以不仅仅是应对面试,在真实的需要进行错误收集的场景中,第一选择也应该是 **`Image`**