一篇文章教你如何捕获前端错误

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/E51lKQOojsvhHvACIyXwhw
作者:黄文佳

目前创新互联已为近1000家的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、吴桥网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

常见错误的分类

对于用户在访问页面时发生的错误,主要包括以下几个类型:

1、js运行时错误

JavaScript代码在用户浏览器中执行时,由于一些边界情况、本地环境的不可控等因素,可能会存在js运行时错误。

而依赖客户端的某些方法,由于兼容性或者网络等问题,也有概率会出现运行时错误。

e.g: 下图是当使用了未定义的变量"foo",导致产生js运行时错误时的上报数据:

一篇文章教你如何捕获前端错误

2、资源加载错误

这里的静态资源包括js、css以及image等。现在的web项目,往往依赖了大量的静态资源,而且一般也会有cdn存在。

如果某个节点出现问题导致某个静态资源无法访问,就需要能够捕获这种异常并进行上报,方便第一时间解决问题。

e.g: 下图是图片资源不存在时的上报数据:

一篇文章教你如何捕获前端错误

3、未处理的promise错误

未使用catch捕获的promise错误,往往都会存在比较大的风险。而编码时有可能覆盖的不够全面,因此有必要监控未处理的promise错误并进行上报。

e.g: 下图是promise请求接口发生错误后,未进行catch时的上报数据:

一篇文章教你如何捕获前端错误

4、异步请求错误(fetch与xhr)

异步错误的捕获分为两个部分:一个是传统的XMLHttpRequest,另一个是使用fetch api。

像axios和jQuery等库就是在xhr上的封装,而有些情况也可能会使用原生的fetch,因此对这两种情况都要进行捕获。

e.g: 下图是xhr请求接口返回400时捕获后的上报数据:

一篇文章教你如何捕获前端错误

各个类型错误的捕获方式

1、window.onerror与window.addEventListener('error')捕获js运行时错误

使用window.onerror和window.addEventListener('error')都能捕获,但是window.onerror含有详细的error堆栈信息,存在error.stack中,所以我们选择使用onerror的方式对js运行时错误进行捕获。

window.onerror = function (msg, url, lineNo, columnNo, error) {
    // 处理错误信息
}
// demo
msg: Uncaught TypeError: Uncaught ReferenceError: a is not defined
error.statck: TypeError: ReferenceError: a is not defined at http://xxxx.js:1:13
window.addEventListener('error', event => (){ 
  // 处理错误信息
}, false);
// true代表在捕获阶段调用,false代表在冒泡阶段捕获。使用true或false都可以,默认为false

2、资源加载错误使用addEventListener去监听error事件捕获

实现原理:当一项资源(如

此步骤的作用是告知浏览器以匿名方式获取目标脚本。这意味着请求脚本时不会向服务端发送潜在的用户身份信息(例如 Cookies、HTTP 证书等)。

添加跨域 HTTP 响应头:

Access-Control-Allow-Origin: *

或者

 Access-Control-Allow-Origin: http://test.com

注意:大部分主流 CDN 默认添加了 Access-Control-Allow-Origin 属性。

完成上述两步之后,即可通过 window.onerror 捕获跨域脚本的报错信息。

解决方案2

难以在 HTTP 请求响应头中添加跨域属性时,还可以考虑 try catch 这个备选方案。

在如下示例 HTML 页面中加入 try catch:




    Test page in http://test.com


    
    // app.js里面有一个foo方法,调用了不存在的bar方法
    



// 运行输出结果如下:

=> ReferenceError: bar is not defined
at foo (http://another-domain.com/app.js:2:3)
at http://test.com/:15:3
=> "Script error.", "", 0, 0, undefined

可见 try catch 中的 Console 语句输出了完整的信息,但 window.onerror 中只能捕获“Script error”。根据这个特点,可以在 catch 语句中手动上报捕获的异常。

总结

上述的错误捕获基本覆盖了前端监控所需的错误场景,但是第三部分指出的两个其他问题,目前解决的方式都不太完美。

对于有使用框架的项目:一是需要有额外的处理流程,比如示例中就需要单独为vue项目进行初始化;二是对于其他框架,都需要单独处理,例如react项目的话,则需要使用官方提供的componentDidCatch方法来做错误捕获。

而对于跨域js捕获的问题:我们并不能保证所有的跨域静态资源都添加跨域 HTTP 响应头;而通过第二种包裹try-catch的方式进行上报,则需要考虑的场景繁多并且无法保证没有遗漏。

虽然存在这两点不足,但前端错误捕获这部分还是和项目的使用场景密切相关的。我们可以在了解这些方式以后,选择最适合自己项目的方案,为自己的监控工具服务。

—— —— 参考文档 —— ——

1.Using XMLHttpRequest:

_https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest_

2.script error 产生的原因和解决办法:

https://www.alibabacloud.com/help/zh/faq-detail/88579.htm

3.JavaScript执行错误:

https://docs.fundebug.com/notifier/javascript/type/javascript.html

4.betterjs的script error:

https://github.com/BetterJS/badjs-report/issues/3

5.Vuejs的errorHandler:

https://cn.vuejs.org/v2/api/index.html#errorHandler

6.React的componentDidCatch:

https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html


文章名称:一篇文章教你如何捕获前端错误
转载源于:http://scjbc.cn/article/peoije.html

其他资讯