基础认知:
快速定位线上问题,捕获一些由于特殊情况导致的无法重现的客户问题
JS 处理异常的方式
try-catch 异常处理
但是 try-catch
处理异常的能力有限, 只能捕获捉到运行时非异步错误,对于语法错误和异步错误就显得无能为力,捕捉不到 。
下面是try-catch基本使用场景
示例:运行时错误
try {
error // 未定义变量
} catch(e) {
console.log('我知道错误了');
console.log(e);
}
然而对于语法错误和异步错误就捕捉不到了 示例:语法错误
window.onerror 异常处理
window.onerror
捕获异常能力比 try-catch
稍微强点,无论是异步还是非异步错误,onerror 都能捕获到运行时错误。
示例:运行时同步错误
/**
* @param {String} msg 错误信息
* @param {String} url 出错文件
* @param {Number} row 行号
* @param {Number} col 列号
* @param {Object} error 错误详细信息
*/
window.onerror=function(msg, url, row, col, error){
console.log('我知道错误了');
console.log({
msg, url, row, col, error
})
return true;
};
error;
示例:异步错误
window.onerror=function(msg,url,row,col,error){
console.log('我知道异步错误了');
console.log({
msg, url, row, col, error
})
return true;
};
//定时器异步
setTimeout(() => {
error;
});
关于 window.onerror
还有两点需要值得注意
1.对于 onerror
这种全局捕获,最好写在所有JS
脚本的前面,因为你无法保证你写的代码是否出错,如果写在后面,一旦发生错误的话是不会被onerror
捕获到的。
2.另外onerror
是无法捕获到网络异常的错误。
当我们遇到<img src="./404.png">
报 404
网络请求异常的时候, onerror
是无法帮助我们捕获到异常的。
可以看到没具体的错误信息和错误状态,但是有一个错误目标对象
这点知识还是需要知道,要不然用户访问网站,图片 CDN 无法服务,图片加载不出来而开发人员没有察觉就尴尬了。
Promise 错误
通过 Promise
可以帮助我们解决异步回调地狱的问题,但是一旦Promise
实例抛出异常而你没有用 catch
去捕获的话,onerror
或 try-catch
也无能为力,无法捕捉到错误。
window.addEventListener('error',(msg,url,row,col,error)=>{
console.log('我感知不到 promise 错误');
console.log(
msg, url, row, col, error
);
}, true);
Promise.reject('promise error');
new Promise((resolve, reject) => {
reject('promise error');
});
new Promise((resolve) => {
resolve();
}).then(() => {
throw 'promise error'
});
所以我们需要主动监听Promise
抛出的全局异常
window.addEventListener("unhandledrejection",function(e){
e.preventDefault()
console.log('我知道 promise 的错误了');
console.log(e.reason);
return true;
});
Promise.reject('promise error');
new Promise((resolve, reject) => {
reject('promise error');
});
new Promise((resolve) => {
resolve();
}).then(() => {
throw 'promise error'
});
前端异常监控现状
Vue全局异常捕获
Vue
全局配置 errorHandler
可以进行全局错误收集,我们可以根据这个特性对前端异常做这样的处理:业务错误直接写在业务里;代码错误、 ajax
请求异常等错误可以进行全局捕获然后抛出,不至于前端页面挂掉
代码层面的错误
import Vue from 'vue'
/**
* err object 异常信息
* vm 错误异常实例
* info 是 Vue 特定的错误信息
*/
// 只在 2.2.0+ 可用
Vue.config.errorHandler=function(err,vm,info){
//此处处理具体的错误信息
return true;
}
import Vue from 'vue'
/**
* err object 异常信息
* vm 错误异常实例
* info 是 Vue 特定的错误信息
*/
// 只在 2.2.0+ 可用
Vue.config.errorHandler=function(err,vm,info){
//此处处理具体的错误信息
return true;
}
但是由于errorHandler
无法捕获 promise
抛出的异常和网络层面资源的异常,所以还需要添加
//捕捉Promise异常
window.addEventListener("unhandledrejection",function(e){
});
//捕获网络错误,资源错误这些类似的错误,需要添加以下事件监听
window.addEventListener("error", function(e){
});
// 记住
window.addEventListener("error",()=>{})
和
`window.onerror=()=>{}`是由区别的
一个让你很开心的Api
navigator.sendBeacon()
方法可用于通过HTTP将少量数据异步传输到Web服务器。
数据可靠,浏览器关闭请求也照样能发
异步执行,不会影响下一页面的加载
同时不会延迟页面的卸载或影响下一导航的载入性能
API使用简单
window.addEventListener('unload',logData,false);
function logData(){
navigator.sendBeacon("http://mob/api/sendLog",{
//参数
});
}
浏览器兼容性很乐观
实现方案
1:数据传递部分 根据浏览器兼容是否支持 navigator.sendBeacon
,如果支持使用 navigator.sendBeacon
发送数据,如果不支持使用创建Image
标签的形式发送数据
var img = new Image();
img.onload =function (){
}
img.src = `http://code/api/sendLog?data=${JSON.stringify({})}`;
//或者
window.addEventListener('unload', function(){
navigator.sendBeacon("http://code/api/sendLog",{});
}, false);
2:需要收集的数据部分
{
accountId:"账号标识ID",
url:"当前页面URL",
browser:"所属浏览器",
version:"浏览器版本",
system:"所属系统",
referer:"入口页面",
jsPath:"异常js文件路径",
errorObj:"异常错误信息json字符串",
connection:"连接网络情况"
}
有想了解更多的小伙伴可以加Q群链接里面看一下,应该对你们能够有所帮助。
有想了解更多前端的技术可以加Q群:1093606290