如何记录前端再用户浏览器上发生的错误并汇报给服务器?

一、代码执行的错误捕获1.try......catch

1.使用try... catch包裹,影响代码可读性。无法处理异步中的错误无法处理语法错误

try{
//可能出现异常的代码
}catch(异常类型  变量名){
//处理异常的代码
}finally{
//无论try块中是否有异常,均实现的代码
}
2.window.onerrorwindow.onerror

比try catch要强那么一丢丢。无论是异步还是非异步错误,onerror都能捕获到运行时错误
缺点:监听不到资源加载的报错onerror,事件处理函数只能声明—次,不会重复执行多个回调:
window.onerror是一个全局变量,默认值为null。当有js运行时错误触发时,window会触发error事件,并执行window.onerror()。onerror可以接受多个参数。

window.onerror = function(message, source, lineno, colno, error) { ... }
 
函数参数:
 
*   message:错误信息(字符串)。可用于HTML onerror=""处理程序中的event。
*   source:发生错误的脚本URL(字符串)
*   lineno:发生错误的行号(数字)
*   colno:发生错误的列号(数字)
*   error:Error对象
 
若该函数返回true,则阻止执行默认事件处理函数,如异常信息不会在console中打印。没有返回值或者返回值为false的时候,异常信息会在console中打印
3.window.addEventListener('error')

可以监听到资源加载报错,也可以注册多个事件处理函数。
监听js运行时错误事件,会比window.onerror先触发,与onerror的功能大体类似,不过事件回调函数传参只有一个保存所有错误信息的参数,不能阻止默认事件处理函数的执行,但可以全局捕获资源加载异常的错误

window.addEventListener('error', function(event) { ... })
 
当资源(如img或script)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。这些error事件不会向上冒泡到window,但可以在捕获阶段被捕获
因此如果要全局监听资源加载错误,需要在捕获阶段捕获事件
//图片加载失败使用默认图片,依旧加载失败超过三次使用base64图片
window.addEventListener('error',function(e){
    let target = e.target, // 当前dom节点
        tagName = target.tagName,
        count = Number(target.dataset.count ) || 0, // 以失败的次数,默认为0
        max= 3; // 总失败次数,此时设定为3
    // 当前异常是由图片加载异常引起的
    if( tagName.toUpperCase() === 'IMG' ){
        if(count >= max){
            target.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//AK3/ALYH+5hX6FV5N4Y/5GHwx/vyf+iJa9ZrysPhoYVShDZu/potDmwWFhhIzhT2bv6aLQ//Z';
        }else{
            target.dataset.count = count + 1;
            target.src = '//xxx/default.jpg';
        }
    }
},true)
4.window.addEventListener("'unhandledrejection')

捕获未处理的promise异常与错误
使用Promise编写异步代码时,使用reject来处理错误。有时,开发者通常会忽略这一点,导致一些错误没有得到处理。例如:

function main() {
    asyncFunc()
    .then(···)
    .then(() => console.log('Done!'));
}

由于没有使用catch方法捕获错误,当asyncFunc()函数reject时,抛出的错误则没有被处理。

浏览器中未处理的Promise错误
一些浏览器(例如Chrome)能够捕获未处理的Promise错误。

。unhandledrejection
监听unhandledrejection事件,即可捕获到未处理的Promise错误:
。reason: Promise的reject值

window.addEventListener('unhandledrejection', event => {
    console.log(event.reason); // Hello, Fundebug!
});
function foo() {
    Promise.reject('Hello, Fundebug!');
}
foo();

当一个Promise错误最初未被处理,但是稍后又得到了处理,则会触发rejectionhandled事件

window.addEventListener('unhandledrejection', event =>
{
    console.log(event.reason); // 打印"Unhandle Promise Error!"
});
 
window.addEventListener('rejectionhandled', event => {
    console.log('rejection handled'); // 1秒后打印"rejection handled"
});
 
function foo() {
    return Promise.reject('Unhandle Promise Error!');
}
 
var r = foo();
 
setTimeout(() => {
    r.catch(e =>{});
}, 1000);

二、资源加载的错误捕获

1. imgObj.onerror()

大家上网的时候肯定见到过加载失败的红叉图片,具体如下图。当然现在Google Chrome与Firefox对其处理会好看一些。

image

其实可以利用图片标签的onerror事件对其处理的,要求其加载失败之后,马上加载一张默认图片,而不是显示为红叉叉。

其代码如下:

  

意为,如果加载s.png这张图片失败了,就马上去加载xx.png这张图片,同时xx.png这张图片要求其以80x80的方式加载。

2. performance.getEntries),获取到成功加载的资源,对比可以间接的捕获错误

浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等等)发出一个HTTP请求。而通过window.performance.getEntries方法,则可以以数组形式,返回这些请求的时间统计信息,每个数组成员均是一个PerformanceResourceTiming对象!

用它小玩儿一下,统计页面上的静态资源加载耗时:

(function () {
    // 浏览器不支持,就算了!
    if (!window.performance && !window.performance.getEntries) {
        return false;
    }

    var result = [];
    // 获取当前页面所有请求对应的PerformanceResourceTiming对象进行分析
    window.performance.getEntries().forEach(function (perf) {
        result.push({
            'url': perf.name,
            'entryType': perf.entryType,
            'type': perf.initiatorType,
            'duration(ms)': perf.duration
        });
    });

    // 控制台输出统计结果
    console.table(result);
})();
如何记录前端再用户浏览器上发生的错误并汇报给服务器?_第1张图片
image.png
  1. window.addEventListener('error', fn, true),会捕获但是不冒泡,所以window.onerror不会触发,捕获阶段可以触发 上面已经有示例代码
    三、错误上报
    —般使用image来上报,用请求图片的方式来上报信息问题;
    使用图片发送get请求,上报信息,由于浏览器对图片有缓存,同样的请求,图片只会发送一次,避免重复上报。
    例: 和请求ajax的方式一样

首先创建一个图片,将其src属性设置为

http://www.baidu.com?n=fff

后期的参数就是需要上报的错误了,可以直接在network中查看参数,类似于ajax请求.


如何记录前端再用户浏览器上发生的错误并汇报给服务器?_第2张图片
image.png

四、借助第三方库
o sentry-javascript

你可能感兴趣的:(如何记录前端再用户浏览器上发生的错误并汇报给服务器?)