摘要:一套完善的前端体系应少不了异常统计与监控,即使有足够的质量保证体系,难免会出现一些意料之外的事,尤其是在复杂的网路环境和运行环境之下。为了保证代码的健壮性以及页面的稳定性,我们从多个方面来做异常的防范和监控。
一套完善的前端体系应少不了异常统计与监控,即使有足够的质量保证体系,难免会出现一些意料之外的事,尤其是在复杂的网路环境和运行环境之下。为了保证代码的健壮性以及页面的稳定性,我们从多个方面来做异常的防范和监控。
三种思路 主动防御对于我们操作的数据,尤其是由 API 接口返回的,时常会有一个很复杂的深层嵌套的数据结构。为了代码的健壮性,很多时候需要对每一层访问都作空值判断,就像这样:
props.user && props.user.posts && props.user.posts[0] && props.user.posts[0].comments && props.user.posts[0].comments[0]
类似的代码大家可能都写过,没写过大概也见到别人写过。看起来确实相当地不美观,有句话说得很棒:
The opposite of beautiful is not ugly, but wrong.
我们得找到一种,更简单、更优雅、更安全的方式来处理这种情形。参考这篇文章:Safely Accessing Deeply Nested Values In JavaScript,文章提到借助 Ramda、Lenses、Lodash 以及 Immutable.js 等类库的方式,并提供一个非常简洁明了的原生解决方案:
function getIn(p, o) { return p.reduce(function(xs, x) { return (xs && xs[x]) ? xs[x] : null; }, o); }
接下来我们这样访问就可以了:
getIn(["user", "posts", 0, "comments"], props)
如果正常访问到,则返回对应的值,否则返回 null。
这里提供的只是主动防御的一种情形,关于如何编写更安全的代码这里不作深入展开。
全局监控浏览器提供 window.onerror API 来帮助我们进行全局的错误监控:
当 JavaScript 运行时错误(包括语法错误)发生时,会执行 window.onerror()`
当一项资源(如 或 )加载失败,能被单一的 window.addEventListener 捕获
/** * @param {String} message 错误信息 * @param {String} source 发生错误的脚本URL * @param {Number} lineno 发生错误的行号 * @param {Number} colno 发生错误的列号 * @param {Object} error Error对象 */ window.onerror = function(message, source, lineno, colno, error) { // ... }
其中 error 对象包含详细的错误堆栈信息,在 IE9 以前,没有这个参数。
针对性捕获 try..catch可以通过 try..catch 来主动抓取错误,想要对一段代码 try..catch,我们可以这样:
try { // ... } catch (error) { handler(error) }
对一个函数做 try..catch 封装:
function tryify(func) { return function() { try { return func.apply(this, arguments) } catch (error) { handleError(error) throw error } } }为什么是 script error
方案已经明确,但还有一些问题。在查看 JavaScript 错误统计时,发现 80% 以上都是 "script error"。原来,当加载自不同域的脚本中发生语法错误时,为避免信息泄露,语法错误的细节将不会报告,而代之简单的 "Script error."
而在大多数情况下,我们的静态资源放在专门的 CDN 服务器上,跟站点并不在一个域,所以如果只是简单的抓取,只会得到一堆意义不大的 script error
解决方案:
添加 CORS 支持
使用 try..catch
添加 CORS 支持需要做两点:
1.在 script 便签添加 crossorigin,默认值 crossorigin="anonymous"
在 require.js 里提供一个 onNodeCreated hook,供我们提供扩展,要添加 crossorigin 属性,如下所示:
在 2.2.0 版本以上可用(很遗憾的是,目前的集成解决方案版本刚好低于这个版本)。
2.同时在 CDN 服务器增加响应头 access-control-allow-orgin,配置允许访问 CORS 的域,否则浏览器直接将禁止加载。
try..catch这一点上面也有提到,算是一种比较通用,可定制强的方案。当然,在性能上也会有一些损耗。
综合考虑,try..catch 通用性更好,但由于其在性能方面的一些损耗,CORS 优于 try..catch
一个监控小工具随后,介绍一个 JavaScript stack trace 的小工具:https://github.com/CurtisCBS/... ,工具由 Curtis 和 mirreal 共同完成。
主要是用于捕获页面 JavaScript 异常报错,捕获异常类型包含:
JavaScript runtime 异常捕捉 √
静态资源 load faided 异常捕捉 √
console.error 的异常捕获 √
try..catch 错误捕获 √
使用方式也很简单,但使用 script mode 引入文件后,调用 init 函数,进行初始化配置和监听
如果是使用 module mode,如下:
// npm install jstracker --save import jstracker from "jstracker" jstracker.init({ concat: false, report: function(errorLogs) { // console.log("send") } })
如果要使用 try..catch 捕获,jstracker 暴露出一个 tryJS 对象,可以处理 try..catch 包装,就像这样:
import jstracker from "jstracker"; this.handleSelect = jstracker.tryJS.wrap(this.handleSelect);
所有错误信息统一由 report 函数处理,可以在此之上做数据处理:
// ubt.js import jstracker from "jstracker"; import utility from "utility"; jstracker.init({ concat: false, report: function(errorLogs) { const errorLog = errorLogs[0]; errorLog.ua = window.navigator.userAgent; ubtTracker.send(errorLog); } }); const ubtTracker = { key: { UBT_JS_TRACKER: "xxxx-xxxx-xxxx" }, send(data) { const value = utility.deserializeUrl(data); xxxx.send(["trace", this.key.UBT_JS_TRACKER, value]); } }; function wrapContext(ctx) { for (const func in ctx) { ctx[func] = jstracker.tryJS.wrap(ctx[func]); } } export { wrapContext, ubtTracker, jstracker };概述
作为开发者以及项目维护者的身份,我们应当编写更安全健壮的代码。但由于环境的多样性,无论再完善的测试,code review 都难免都所疏漏,我们需要一套监控系统来完善整个前端体系。
在监控的时候,出于同源安全策略无法拿到准确的错误信息,在此,有两种解决方案:
增加 CORS 支持
使用 try..catch 进行异常捕获
最后,我们对整个监控工作封装了一个基础的核心,可以监控 JavaScript Runtime 异常,资源加载异常,以及 try..catch 捕获异常等,并给出一个实际工作中的示例。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/83585.html
摘要:前端日报精选新的长度单位你知道么高阶函数一点通的故事隔行扫描算法专题之数组去重全家桶每个人都能做的网易云音乐腾讯前端团队社区中文前端推荐第天听说你缺少一个顺手的图床知乎专栏译怎样创建定制表单组件碎语掘金函数式编程到底是个啥 2017-06-22 前端日报 精选 CSS 新的长度单位 fr 你知道么?高阶函数一点通png的故事:隔行扫描算法JavaScript专题之数组去重 · Issu...
摘要:摘要徒手写错误监控。为什么用定时器呢,因为在单页应用中,路由的切换和地址栏的变化是无法被监控的,我确实没有想到特别好的办法来监控,所以用了这种方式,如果有人有更好的办法,请给我留言,谢谢。 摘要: 徒手写JS错误监控。 作者:一步一个脚印一个坑 原文:搭建前端监控系统(二)JS错误监控篇 Fundebug经授权转载,版权归原作者所有。 背景:市面上的监控系统有很多,大多收费,对于...
摘要:年月,遭到了攻击,这个事件足以警示我们。自从年双十一正式上线,累计处理了亿错误事件,付费客户有金山软件百姓网等众多品牌企业。 译者按: 10 年前的博客似乎有点老了,但是XSS 攻击的威胁依然还在,我们不得不防。 原文: XSS - Stealing Cookies 101 译者: Fundebug 本文采用意译,版权归原作者所有 窃取Cookie是非常简单的,因此不要轻易相信...
摘要:译者按从标准,语法以及模块角度来看,的发展让人目不暇接,那么面试题也得与时俱进。因此,手动检查所有依赖是不现实的。为,加之后返回。自从年双十一正式上线,累计处理了亿错误事件,得到了金山软件百姓网等众多知名用户的认可。 译者按: 从ECMAScript标准,Node.js语法以及NPM模块角度来看,Node.js的发展让人目不暇接,那么面试题也得与时俱进。 原文: Node.js In...
阅读 1692·2021-11-22 15:33
阅读 1954·2021-10-08 10:04
阅读 3521·2021-08-27 13:12
阅读 3367·2019-08-30 13:06
阅读 1440·2019-08-29 16:43
阅读 1362·2019-08-29 16:40
阅读 694·2019-08-29 16:15
阅读 2726·2019-08-29 14:13