前端错误监控
为什么要做前端错误监控?
1. 为了保证产品的质量
2. 有些问题只存在于线上特定的环境
3. 后端错误有监控,前端错误没有监控
前端错误的分类
前端错误分为两类: 即时运行错误和资源加载错误
即使运行错误的捕获方式
即时运行错误的捕获方式分为两类
- try...catch
- window.onerror
try...catch
通过try...catch我们能够知道出错的信息,并且也有堆栈信息可以知道在哪个文件第几行第几列发生错误
try { // 代码段 } catch (err) { console.log(err.message) }
缺点:
- 没法捕捉try,catch块,当前代码块有语法错误,js解释器压根都不会执行当前这个代码块,所以也就没办法被catch住;
- 没法捕捉到全局的错误事件,也即是只有try,catch的块里边运行出错才会被你捕捉到,这里的块你要理解成一个函数块
关于第一个缺点,我们没有任何解决办法,但是一般语法阶段我们是能在开发阶段/或者用工具检测到的,于是乎它就被忽略了
第二个缺点应该怎么理解呢? try...catch只能捕捉到当前执行流里边的运行错误,对于异步回调来说,是不属于这个try...catch块的
window.onerror
全局捕获。window.onerror一样可以拿到出错的信息以及文件名、行号、列号等信息,还可以在window.onerror最后return true让浏览器不输出错误信息到控制台
/* * @param msg{string}:错误消息 * @param url{string}:引发错误的脚本的url * @param line{number}:发生错误的代码行 * @param colunm{number}:发生错误的代码列 * @param error{object}:错误对象 */ window.onerror = function (msg, url, line, colunm, error) { // 返回 true 则错误消息不显示在控制台,返回 false,则错误消息将会展示在控制台 return true; }
最后window.onerror的实现方法
window.onerror = function (msg, url, line, col, error) { //没有url不上报!上报也不知道错误 if (msg != "script error." && !url) { return true; } settimeout(function () { var data = {}; //不一定所有浏览器都支持col参数 col = col || (window.event && window.event.errorcharacter) || 0; data.url = url; data.line = line; data.col = col; if (!!error && !!error.stack) { //如果浏览器有堆栈信息 //直接使用 data.msg = error.stack.tostring(); } else if (!!arguments.callee) { //尝试通过callee拿堆栈信息 var ext = []; var f = arguments.callee.caller, c = 3; //这里只拿三层堆栈信息 while (f && (--c > 0)) { ext.push(f.tostring()); if (f === f.caller) { break; //如果有环 } f = f.caller; } ext = ext.join(","); data.msg = ext; } //把data上报到后台! console.log(data) }, 0); return true; };
资源加载错误
object.onerror
img、script标签都可以添加onerror事件,当资源请求失败的时候,都会触发该事件
var img = document.getelementbyid('img'); img.onerror=function(){ console.log("出错啦"); }
performance.getentries()
performance是h5的新特性之一,使用该方法能获取到当前页面已经加载到的资源,返回的是一个数组对象。下面给出一个例子
获取页面中没有成功加载的图片资源?
步骤一:通过performance.getentries()获取已经加载了的图片资源
let arr = [], reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i); performance.getentries().foreach(item => { if (reg.test(item.name)) { arr.push(item.name) } })
步骤二:获取页面中所有的img标签
let imglist=document.getelementbytagname('img')
步骤三:利用获取到的img的长度减去已经加载到的长度,如果大于0的部分,就是加载失败的
let arr = [], imglist=null, num=0, reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i); performance.getentries().foreach(item => { if (reg.test(item.name)) { arr.push(item.name) } }) imglist=document.getelementsbytagname('img'); num=imglist.length-arr.length;
error事件捕获
资源加载错误,虽然会阻止冒泡,但是不会阻止捕获。true:捕获,false:冒泡
// window.addeventlistener第三个参数是true的时候是捕获的过程,false是冒泡的过程 window.addeventlistener('error',function(e){ console.log("捕获",e) },true)
跨域的js文件异常捕获
为了提升web性能,大部分web产品都有cdn部署,将资源部署到不同的域名上,但是我们都知道浏览器是有同源策略的,当加载不同域名的脚本发生错误时,语法错误的细节不会报告,仅返回"script error",针对这种问题,可以在服务器上设置"access-control-allow-origin:*",在请求资源的script标签上加上crossorigin属性即可
<script src="xxxx/js/store.js" crossorigin></script>
推荐阅读
-
android studio错误: 常量字符串过长的解决方式
-
django使用ajax post数据出现403错误如何解决
-
前端之道
-
Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)
-
inux 磁盘监控分析
-
使用nginx代理gogs遇到推送代码错误的问题(RPC failed; HTTP 413 curl 22 The requested URL returned error: 413)
-
ASP.net基础知识之常见错误分析
-
让sql2005运行在独立用户下出现 WMI 提供程序错误的解决方式
-
微服务业务监控和行为分析怎么做?试试日志埋点
-
SQL Server 2005 DTS导入平面数据出现错误解决方案