前端所有错误捕获方法和上报方案

前端所有错误类型以及捕获方式

JS Error

1. window.addEventListener('error',function(err){ 
        console.log('事件捕获...',err) 
    },true) 
2. window.onerror=function(err){ 
        console.log('事件捕获...',err) 
    }

报错信息:Script error .

当加载自不同域的脚本中发生语法错误时,浏览器为避免信息泄露的安全风险,语法错误的细节将不会报告给浏览器console中,而是使用"Script error."信息代替。

一般而言,如果是第三方的JS资源,和页面自身的URL产生了跨域问题,所以引起了"Script Error"。

解决方法:我们为 script 标签添加 crossOrigin 属性。

<script src='xxx.com' crossOrigin />

定时器内部函数抛出错误

定时器内部函数的错误会抛到顶层,无法被try...catch

try { 
    setTimeout(() => { 
        null.map(v => v); }, 1000) 
    } 
catch(e) { 
    console.log('捕获到异常:',e); 
}
1. window.onerror = function(message, source, lineno, colno, error) { 
        console.log('捕获到异常:',{message, source, lineno, colno, error}); 
   } 
2. window.addEventListener('error',function(err){ 
        console.log('捕获到异常...',err) 
   },true)

静态资源加载的异常

当一项资源(如图片和脚本加载失败),加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror处理函数。这些error事件不会向上冒泡到window, 不过(至少在 Chrome 中)能被全局的addEventListener 捕获。

window.onerror不能捕捉静态资源加载的异常,addEventListener可以捕捉到。

window.addEventListener('error', (error) => { 
    console.log('捕获到异常:', error); 
}, true)

iframe内部异常

可通过window.onerror捕获

<iframe src="./iframe.html" frameborder="0"></iframe> 
<script>
        window.frames[0].onerror = function (message, source, lineno, colno, error) { 
            console.log('捕获到 iframe 异常:', {message, source, lineno, colno, error}); 
        }; 
</script>

网络请求的异常

由于网络请求异常不会事件冒泡,就算在捕获中无法判断 HTTP 的状态是 404 或是比如 500 等等,所以还需要配合服务端日志才进行排查分析才可以。

所以我们一般配合一些请求库去完成完成网络请求异常的捕获。比如axios进行回调捕获,或者ajax回调捕获,或是promise化catch。

Promise Catch

unhandledrejection 只能捕获未显式处理的Promise异常

// 能触发 unhandledrejection ,因为未显式处理reason 
Promise.reject('error').then() 
Promise.reject('error').then(console.log) 

// 不能触发 unhandledrejection ,因为已处理reason 
Promise.reject('error').then(console.log, console.log) 
// 不能触发 unhandledrejection ,因为没处理reason,直接抛出异常 
Promise.reject('error')

监听捕获方法

扫描二维码关注公众号,回复: 14344644 查看本文章
// 全局监听 Uncaught Promise Error。
window.addEventListener("unhandledrejection", function(e){ 
    // e.preventDefault(); // 阻止异常向上抛出 
    console.log('捕获到异常:', e); 
});
window.onunhandledrejection = function(e){ 
    // e.preventDefault(); // 阻止异常向上抛出到全局,不在console中显示 
    console.log('捕获到异常:', e); 
};

常见框架处理

React错误处理

componentDidCatch(error, info) { 
    // Display fallback UI 
    this.setState({ hasError: true }); 
    // You can also log the error to an error reporting service 
    logErrorToMyService(error, info); 
}

Vue错误处理

Vue.config.errorHandler = function (err, vm, info) { 
// vm为抛出异常的 Vue 实例 
// info为 Vue 特定的错误信息,比如错误所在的生命周期钩子 
    let { 
    message, // 异常信息 
    name, // 异常名称 
    script, // 异常脚本url 
    line, // 异常行号
    column, // 异常列号 
    stack // 异常堆栈信息 
    } = err;
})

数据上报方式(可用于数据埋点)

关闭或者最小化浏览器时回调

  1. beforeunload (关闭前确认弹窗) 部分移动端不触发
  2. unload 关闭时 部分移动端不触发
  3. pagehide 隐藏时 部分移动端不触发

延迟浏览器关闭或跳转的方法:

用户场景:当用户导航到另一个页面或者关闭页面,希望关闭或跳转前将数据完整发送

  1. 创建一个img元素并设置它的src。阻塞主线程,大多数浏览器会延迟卸载以加载图像。
    • 在src中创建埋点url,服务端通过get方式接收
    • 原理:占用浏览器主线程,大多数浏览器会延迟卸载以加载图像。
  2. 创建几秒钟的无操作循环。
let currTime=new Date().valueOf())
while(new Date()>currTime+3000){}
  1. 通过配置将XHR同步发送请求
    • axios默认是异步的,浏览器可能会过早关闭或跳转导致取消发送
    • 通过配置将XHR改为同步发送请求,但是可能会影响用户跳转的速度。
  2. sendBeaconAPI 64KB限制 IE兼容性问题 post请求
    • body大小64KB限制 IE兼容性问题 post请求
    • 浏览器将 Beacon 请求排队让它在空闲的时候执行
    • 浏览器进行了优化:可以将 Beacon 请求合并到其他请求上,一同处理, 尤其在移动环境下。
    • 异步发送 不阻塞进程

猜你喜欢

转载自juejin.im/post/7115318629020729352