亲宝软件园·资讯

展开

JS前端错误监控捕获以及上报方法详解

let_code 人气:0

前端错误捕获方法

前端捕获错误的方法:

try..catch:捕获的异常必须是线程执行进入到try...catch且try...catch未执行完的时候抛出来。

语法异常在语法检查阶段就报错了,线程尚未进入try...catch代码块,所以无法捕获到异常。

try {
    a.
}catch(e) {
    console.log('catch error:', e)
}

不能捕获setTimeout或者Promise中的错误。以下错误都不能捕获。如果想捕获,要将try...catch放入到异步代码内部。

        try {
            new Promise((res, rej) => {
                rej('promise reject error')
                // throw new Error('promise throw error')
            })
        } catch (e) {
            console.log('catch error:', e)
        }
​
​
        try {
            setTimeout(() => {
                throw new Error('setTimeout throw error')
            }, 0)
        } catch (e) {
            console.log('catch error:', e)
        }

能捕获async 异常

        async function fn() {
            try {
                let res = await new Promise((res, rej) => {
                    // rej('my reject err') // unhandledrejection 可以处理
                    throw Error('my throw error') // unhandledrejection 可以处理
                })
            } catch (err) {
                console.log('catch err', err)
            }
        }
​
        fn()

window.onerror:当资源加载失败或无法使用时,会在Window对象触发error事件,无法捕获promise错误,可以捕获setTimeout错误。

当加载自不同域的脚本中发生语法错误时,浏览器为避免信息泄露的安全风险,语法错误的细节将不会报告给浏览器console中,而是使用"Script error."信息代替。解决办法是为 script 标签添加 crossOrigin 属性,并且服务端配置Access-Control-Alow-Origin:*

unhandledrejection:当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件

不同场景错误处理方式

总结先行: addEventListener('error') + addEventListener('unhandledrejection') 的方式恰好能够覆盖5种异常错误(同步任务,普通异步任务,promise任务,async任务,资源加载)的捕获。

可以将unhandledrejection捕获到的错误throw出来让error进行捕获之后统一上报。

promise:常常配置catchhandler进行处理,没有处理的rejected的promise通过unhandledrejection

// 能触发 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')

React捕获错误:错误边界(Error Boundaries)

部分 UI 的 JavaScript 错误不应该导致整个应用崩溃,错误边界是一种 React 组件,这种组件可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。错误边界可以捕获发生在整个子组件树的渲染期间、生命周期方法以及构造函数中的错误。

错误边界无法捕获以下场景中产生的错误:

Vue捕获错误:

全局-Vue.config.errorHandler:指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。

生命周期钩子-errorCaptured:在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传

传播规则:

错误信息上报

捕获到错误信息后进行上报,对于前端监控很重要。

上报的方式有三种:

ajax进行上报

发现错误的时候上传错误到接口进行存储。

但是存在一些问题:

image上报

由于图片天然可跨域,又能兼容所有的浏览器,而js和css等其他资源文件则可能出现安全拦截和跨域加载问题。

let img = new Image()
img.src='请求的url'

但由于是一个get请求,上报的数据量在不同的浏览器下上限不一致(2kb-8kb),这就可能出现超出长度限制而无法上报完整数据的情况。因此,图片上报也是一个“不安全”的方式。

sendBeacon

sendBeacon

navigator.sendBeacon() 方法可用于通过 HTTP POST 将少量数据 异步 传输到 Web 服务器。

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术

这个方法主要用于满足统计和诊断代码的需要,这些代码通常尝试在卸载(unload)文档之前向 Web 服务器发送数据。过早的发送数据可能导致错过收集数据的机会。然而,对于开发者来说保证在文档卸载期间发送数据一直是一个困难。因为用户代理通常会忽略在 unload 事件处理器中产生的异步 XMLHttpRequest

navigator.sendBeacon(url, data);

使用 sendBeacon() 方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能,这意味着:

加载全部内容

相关教程
猜你喜欢
用户评论