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

Victoria ·
更新时间:2024-09-20
· 1090 次阅读

目录

前端错误捕获方法

不同场景错误处理方式

错误信息上报

ajax进行上报

image上报

sendBeacon

前端错误捕获方法

前端捕获错误的方法:

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进行捕获之后统一上报。

跨域资源加载问题:window.addEventListener('error',()=>{}),并且script 标签添加 crossOrigin 属性,并且服务端配置Access-Control-Alow-Origin

定时器内部函数抛出错误:window.onerror或者window.addEventListener('error',()=>{})

静态资源加载的异常:window.addEventListener('error')可以捕获,但是window.onerror不能捕获

网络请求的异常:axios的响应拦截器

线上压缩代码:开启sourceMap

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,而并不会渲染那些发生崩溃的子组件树。错误边界可以捕获发生在整个子组件树的渲染期间、生命周期方法以及构造函数中的错误。

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

事件处理(了解更多)

异步代码(例如 setTimeoutrequestAnimationFrame 回调函数)

服务端渲染

它自身抛出来的错误(并非它的子组件)

Vue捕获错误:

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

从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。同样的,当这个钩子是 undefined 时,被捕获的错误会通过 console.error 输出而避免应用崩溃。

从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了。

从 2.6.0 起,这个钩子也会捕获 v-on DOM 监听器内部抛出的错误。另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理。

错误追踪服务 Sentry 和 Bugsnag 都通过此选项提供了官方支持。

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

传播规则:

默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。

如果一个组件的 inheritance chain (继承链)或 parent chain (父链)中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。

如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler

一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler

错误信息上报

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

上报的方式有三种:

ajax进行上报

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

但是存在一些问题:

有严格的跨域限制

上报请求可能会阻塞业务

请求容易丢失(被浏览器强制cancel)

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

数据发送是可靠的。

数据异步传输。

不影响下一导航的载入。

以上就是JS前端错误监控捕获以及上报方法详解的详细内容,更多关于JS前端错误监控捕获上报的资料请关注软件开发网其它相关文章!



监控 方法 捕获 js

需要 登录 后方可回复, 如果你还没有账号请 注册新账号