浏览器异常信息捕获

一、产生异常的原因
  1. 逻辑错误
    1. 业务逻辑判断条件错误
    2. 事件绑定顺序错误
    3. 调用栈时序错误
    4. 错误的操作js对象
  2. 数据类型出错
    1. 将null视作对象读取property
    2. 将undefined视作数组进行遍历
    3. 将字符串形式的数字直接用于加运算
    4. 函数参数未传
  3. 语法句法错误
  4. 网络错误
    1. 服务端未返回数据但仍200,前端按正常进行数据遍历
    2. 提交数据时网络中断
    3. 服务端500错误时前端未做任何错误处理
  5. 系统错误
    1. 内存不够用
    2. 磁盘塞满
    3. 壳不支持API
    4. 不兼容
二、错误的分类
  1. JS运行时错误
    1. JavaScript代码在用户浏览器中执行时,由于一些边界情况、本地环境的不可控等因素,可能会存在js运行时错误。
    2. 依赖客户端的某些方法,由于兼容性或者网络等问题,也有概率会出现运行时错误。
  2. 资源加载错误
    1. 静态资源包括js、css以及image等。现在的web项目,往往依赖了大量的静态资源,而且一般也会有cdn存在。
  3. 未处理的promise错误
  4. 异步请求错误(fetch与xhr)
    1. 如果使用的是原生的方法,那么需要对错误捕获进行封装
三、捕获方式
  1. window.onerror
    当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。

  2. window.addEventListener(‘error’,fn)
    当一项资源(如<img>或<script>)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。这些error事件不会向上冒泡到window,不过(至少在Firefox中)能被单一的window.addEventListener捕获。

  3. window.addEventListener(“unhandledrejection”,fn)
    当Promise被 reject 且没有 reject 处理器的时候,会触发unhandledrejection事件;这可能发生在window下,但也可能发生在Worker中。这对于调试回退错误处理非常有用。

        // js错误监听
         window.onerror = function (msg, url, row, col, error) {
            console.warn('js错误监听====>',msg, url, row, col, error);
        };

        // 网络错误监听
        window.addEventListener('error', (error) => {
            console.warn('网络错误监听',error);
        }, true);

        //promise错误监听
        window.addEventListener("unhandledrejection", event => {
            console.warn(`promise错误监听: ${event.reason}`);
        });
四、各个类型错误的捕获方式
  1. JS运行时错误

    1. window.onerror
    2. window.addEventListener(‘error’)
    3. 使用window.onerror和window.addEventListener(‘error’)都能捕获,但是window.onerror含有详细的error堆栈信息
  2. 资源加载错误

    1. 原理:当一项资源(如<img>或<script>)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。
    2. 这些error事件不会向上冒泡到window,不过能被window.addEventListener在捕获阶段捕获。
    3. 注意点
      1. addEventListener也能够捕获js错误,因此需要过滤避免重复上报,判断为资源错误的时候才进行上报
      2. 不同浏览器下返回的 error 对象可能不同,需要注意兼容处理。
  3. Promise错误

    1. 原理:当promise被reject并且错误信息没有被处理的时候,会抛出一个unhandledrejection。
    2. 在 promise 中使用 catch 可以非常方便的捕获到异步 error 。没有写 catch 的 Promise 中抛出的错误无法被 或 try-catch 捕获到,所以我们务必要在 Promise 中不要忘记写 catch 处理抛出的异常。
    3. 这个错误不会被window.onerror以及window.addEventListener(‘error’)捕获,但是有专门的window.addEventListener(‘unhandledrejection’)方法进行捕获处理。
    4. 为了防止有漏掉的 Promise 异常,建议在全局增加一个对 unhandledrejection 的监听,用来全局监听Uncaught Promise Error。
  4. fetch与xhr错误的捕获

    1. 对于fetch和xhr,我们需要通过改写它们的原生方法,在触发错误时进行自动化的捕获和上报。
  5. Vue 错误

    Vue.config.errorHandler = (err, vm, info) => {
    
    console.error('通过vue errorHandler捕获的错误');
    
    console.error(err);
    
    console.error(vm);
    
    console.error(info);
    
    }
    
  6. React 错误

    1. componentDidCatch
    2. error boundary

    React 16 提供了一个内置函数 componentDidCatch,使用它可以非常简单的获取到 react 下的错误信息

    componentDidCatch(error, info) {
    
    console.log(error, info);
    
    }
    
  7. iframe 异常

    1. 对于 iframe 的异常捕获,我们还得借力 window
  8. error

    1. 一般情况,如果出现 error 这样的错误,基本上可以确定是出现了跨域问题。
    2. 解决方案
      1. 跨源资源共享机制( CORS )
      2. 动态去添加 js 脚本
    3. 服务器端需要设置:Access-Control-Allow-Origin
  9. 崩溃和卡顿

    1. 利用 window 对象的 load 和 beforeunload 事件实现了网页崩溃的监控。
    2. 使用 Service Worker 来实现网页崩溃的监控
五、异常采集
  1. 采集内容
    1. 用户信息: 出现异常时该用户的信息,例如该用户在当前时刻的状态、权限等,以及需要区分用户可多终端登录时,异常对应的是哪一个终端。
    2. 行为信息:用户进行什么操作时产生了异常:所在的界面路径;执行了什么操作;操作时使用了哪些数据;当时的API吐了什么数据给客户端;如果是提交操作,提交了什么数据;上一个路径;上一个行为日志记录ID等。
    3. 异常信息:产生异常的代码信息:用户操作的DOM元素节点;异常级别;异常类型;异常描述;代码stack信息等。
    4. 环境信息:网络环境;设备型号和标识码;操作系统版本;客户端版本;API接口版本等。
  2. 异常捕获
    前端捕获异常分为全局捕获和单点捕获。全局捕获代码集中,易于管理;单点捕获作为补充,对某些特殊情况进行捕获,但分散,不利于管理。
    1. 全局捕获
      通过全局的接口,将捕获代码集中写在一个地方,可以利用的接口有:

      1. window.addEventListener(‘error’) / window.addEventListener(“unhandledrejection”) 等
      2. 框架级别的全局监听,例如aixos中使用interceptor进行拦截,vue、react都有自己的错误采集接口
      3. 通过对全局函数进行封装包裹,实现在在调用该函数时自动捕获异常
      4. 对实例方法重写(Patch),在原有功能基础上包裹一层,例如对console.error进行重写,在使用方法不变的情况下也可以异常捕获
    2. 单点捕获
      在业务代码中对单个代码块进行包裹,或在逻辑流程中打点,实现有针对性的异常捕获:

      1. try…catch
      2. 专门写一个函数来收集异常信息,在异常发生时,调用该函数
      3. 专门写一个函数来包裹其他函数,得到一个新函数,该新函数运行 结果和原函数一模一样,只是在发生异常时可以捕获异常
    3. 跨域脚本异常
      由于浏览器安全策略限制,跨域脚本报错时,无法直接获取错误的详细信息,只能得到一个Script Error。例如,我们会引入第三方依赖,或者将自己的脚本放在CDN时。

参考链接:
来自腾讯CDC团队的前端异常监控解决方案
一篇文章教你如何捕获前端错误
友好的处理前端异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值