前端异常捕获与上报

能捕获的错误类型

  • 语法错误
  • 运行时异常
  • 资源加载异常
    • img
    • script
    • link
    • audio
    • video
    • iframe
    • ...外链资源的DOM元素
  • 异步请求异常
  • Promise异常
  • CSS中资源异常
    • font-face
    • background-image
    • 其他的暂时无法捕获

@font-face
background-image
...暂时无法捕获

捕获方式

  • try-catch
  • window.addEventListener('error', cb, true)
  • window.addEventListener("unhandledrejection", cb)
  • Promise.then().catch(cb)
  • 定制异步请求代码

代码

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="http://baidu.com/test.js"></script>
</head>
<body>
	<img src="sss" onerror="javascript:console.log(this)">
	<div>hello world</div>

	<script type="text/javascript">
		function report() {
			(new Image()).src="http://post.error.com?data=xxx"
		}
		// DOM2
		// 全局捕获及时代码运行错误,比如语法错误、逻辑错误
		// 还有资源加载错误,通常是404或加载超时
		// 第三个参数一定true,为true表示在捕获阶段触发,为false就是冒泡阶段,那获取不到错误事件。
		window.addEventListener("error", function(ev) {
			console.log('捕获',ev)
		}, true);
        
        // DOM4
		// 捕获 Promise 未处理的异常
		window.addEventListener('unhandledrejection', function(e) {
			e.preventDefault();
			console.log('捕获到未处理的promise: ', e);
		}, false);
		new Promise((resolve, reject) => {
			reject('jiadsf');
		});
		fetch('http://example.com/movies.json')
		try {
			JSON.parse('{123123')	
		} catch (e) {
			// 捕获到JSON.parse的异常,虽然能全局捕获,但找不到错误对象ev.error
		}
		

	</script>
</body>
</html>

日志上报

简单版,使用图片。优点实现简单可跨域。

function report() {
	(new Image()).src="http://post.error.com?data=xxx"
}

进阶版,使用 Navigator.sendBeacon(),兼容性 Chrome 39+,IE 不兼容。

// navigator.sendBeacon(url, data);

navigator.sendBeacon('http://post.error.com', 'data=xxxxx');

// data 可以传递 string 类型,那么后端接口里接到的请求,Content-Type 为 text/plain,就当字符串处理data

此方法可用于满足统计和诊断代码的需要,可以批量发送数据,并且浏览器保证它不卡渲染线程,在页面 load/unload 事件里处理异步动作而不影响渲染,并且天然跨域。缺点只是兼容性了。

综上上报时优先使用 sendBeancon,监测到不兼容则用 img。

function reportData(url, data) {
    if (navigator.sendBeacon) {
        navigator.sendBeacon(url, data);
    } else {
        (new Image()).src = `${url}?data=${data}`
    }
}

export default reportData;

参考

MDN-Navigator.sendBeacon()

前端异常监控-看这篇就够了

使用sendBeacon进行前端数据上报

posted @ 2020-03-21 12:34  Ever-Lose  阅读(453)  评论(0编辑  收藏  举报