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

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

作者: 威少带我砍三双 | 来源:发表于2021-03-22 10:34 被阅读0次

    一、代码执行的错误捕获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

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

    其代码如下:

    <img src="s.png" onerror="javascript:this.src='xx.png';this.width=80;this.height=80;" />  
    

    意为,如果加载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);
    })();
    
    image.png
    1. window.addEventListener('error', fn, true),会捕获但是不冒泡,所以window.onerror不会触发,捕获阶段可以触发 上面已经有示例代码
      三、错误上报
      —般使用image来上报,用请求图片的方式来上报信息问题;
      使用图片发送get请求,上报信息,由于浏览器对图片有缓存,同样的请求,图片只会发送一次,避免重复上报。
      例: 和请求ajax的方式一样
    <script>
    (new Image()).src="http://www.baidu.com?n=fff"
    </script>
    

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

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

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


    image.png

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

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/jptzcltx.html