上线的项目难免会有错误,通过分析日志能够有效、准确地定位、重现并解决错误,从而提升产品体验。以下是根据资料以及目前需求所实现的一个前端日志采集的方案。
try { } catch (e) { }
:
在可能出现错误的地方主动进行捕获,上传。try {
// 代码块
var a = 1;
a.a.a;
} catch (e) {
// 捕获的错误
console.log(err);
// TypeError: Cannot read property 'a' of undefined at test.html:33
// 上报信息
// ajax upload (err)
}
这种方式加上好的捕获处理,能够让程序不至于因为错误而崩溃。 但是,需要包裹代码块,这点可以用一个入口函数来解决:
try {
init();
} catch (err) {
// ajax upload (err)
}
即便如此也不能保证捕获所有错误:
function init() {
//...
$("button").click(function() {
var a = 1;
a.a.a;
});
//...
}
try {
init();
} catch (err) {
// 此处不能捕获到错误
}
// 而是控制台报未捕获的错误:Uncaught TypeError: Cannot read property 'a' of undefined
想要使用try ... catch
捕获异步代码的错误,就要在代码执行的地方进行捕获:
function init() {
//...
$("button").click(function() {
try {
var a = 1;
a.a.a;
} catch (e) {
// 捕获错误
}
});
//...
}
init();
window.onerror
监听页面错误/**
* @param {String} msg 错误信息
* @param {String} scripturl 出错脚本的url
* @param {Long} line 错误行号
* @param {Long} col 错误列号
* @param {Object} error 错误的详细信息
*/
window.onerror = function(msg, scripturl, line, col, error) {
// return true; 可屏蔽 console 报错显示,此处依旧选择显示
// 跨域脚本的错误,捕获的结果是 Script error.
// 可通过使用 crossorigin 信任
if (msg == "Script error.") {
return false;
}
// 采用异步的方式
// 参考的使用异步的方式,避免阻塞,没遇见过也不想遇到
setTimeout(function() {
var data = {};
data.scripturl = scripturl;
data.line = line;
// 不一定所有浏览器都支持col参数
data.col = col || (window.event && window.event.errorCharacter) || 0;
if (!!error && !!error.stack) {
// 如果浏览器有堆栈信息
// 直接使用
data.msg = error.stack.toString();
} else {
// 参考资料中有通过 arguments.callee.caller 获取错误信息
// 但是严格模式下不允许访问 arguments.callee
// 故此处无法获取错误信息
data.msg = "无法获取详细信息";
}
// 把 data 错误信息上报到后台
}, 0);
return false;
};
这种方式相对try...catch
显得方便多了,能够实现全局监听错误,有一点要注意的是实现监听最好放在前面,以免因为错误导致 js 中断从而根本没有绑定上监听事件。
通过重写XMLHttpRequest
对象的open
、send
方法进行信息收集。
var xhrArray = [];
var xhrlog = {
// 记录请求的 url
reqUrl: "",
// 记录请求的方法
reqMethod: "",
// 保存原生的 open 方法
xhrOpen: XMLHttpRequest.prototype.open,
// 保存原生的 send 方法
xhrSend: XMLHttpRequest.prototype.send,
init: function() {
var _self = this;
// 重写 open
XMLHttpRequest.prototype.open = function() {
// 先在此处取得请求的url、method
_self.reqUrl = arguments[1];
_self.reqMethod = arguments[0];
// 在调用原生 open 实现重写
_self.xhrOpen.apply(this, arguments);
};
// 重写 send
XMLHttpRequest.prototype.send = function() {
// 记录xhr
var xhrmsg = {
url: _self.reqUrl,
type: _self.reqMethod,
// 此处可以取得 ajax 的请求参数
data: arguments[0] || {}
};
this.addEventListener("readystatechange", function() {
if (this.readyState === 4) {
// 此处可以取得一些响应信息
// 响应信息
xhrmsg["res"] = this.response;
xhrmsg["status"] = this.status;
this.status >= 200 && this.status < 400
? (xhrmsg["level"] = "success")
: (xhrmsg["level"] = "error");
xhrArray.push(xhrmsg);
}
});
_self.xhrSend.apply(this, arguments);
};
}
};
// 初始化,重写 xhr 方法
xhrlog.init();
// 至此,xhrArray 中就记录着当前页面的请求信息
至此,稍加修改、组合,就是一个简单而又实用的前端日志收集工具了,还是十分有意义的。
// 截止目前这份系统还没显露出威力,那,一定是因为我们的代码写的稳啊 ( ̄ ▽  ̄)/
前端代码异常监控 :rocket: lajax - 前端日志解决方案 前端代码异常日志收集与监控 JavaScript 错误处理