前端错误监控

目录

js运行时错误

普通错误

错误捕获

捕获到的错误信息

未捕获的Promise错误

错误捕获方式

更推荐的做法

关于Vue 的 errorHandler

关于 React 的 ErrorBoundary

网络请求错误

静态资源加载失败

如何监控静态资源加载失败呢?

 Script error,拿不到错误信息?

捕获AJAX 错误

捕获 fetch 错误


前端错误监控大分为两大类:js运行时错误,网络请求错误

js运行时错误可分为:普通错误,未捕获的Promise错误

网络请求错误可分为:静态资源加载失败,AJAX (XHR,fetch)请求失败

js运行时错误

普通错误

比如我们调用了一个不存在函数

错误捕获

    window.addEventListener('error', function (e) {console.log('error1:', e)// 上报// monitorSDK.report(你要上报的信息)})window.onerror = function (e) {console.log('error2:', e)}xxx();

捕获到的错误信息

未捕获的Promise错误

可以看到,如果一个Promise发生错误,但是没有用catch进行处理,将会抛出一个错误,这种错误如何捕获呢?用第1种的方式可行吗?这里新增一个错误捕获方式

    window.addEventListener('error', function (e) {console.log('error1:', e)})window.onerror = function (e) {console.log('error2:', e)}window.addEventListener('unhandledrejection',function(e){console.log('unhandledreject:', e)})new Promise(()=>xxx);

错误捕获方式

可以看到,第1种并不能捕获Promise错误,而是需要用  window.addEventListener('unhandledrejection') 来捕获

更推荐的做法

为了使代码更加健壮,建议 catch 所有的Promise错误

关于Vue 的 errorHandler

Vue为了防止应用崩溃,内部进行了 try catch ,导致没有错误抛出,我们可以通过在 errorHandler 里拿到错误信息,并主动上报

关于 React 的 ErrorBoundary

React 针对应用渲染时发生错误的处理方式和Vue不一样,如果渲染发生错误并且没有用ErrorBounbary包裹,整个应用将崩溃,React认为不显示比显示一个错误的UI更合理,当然了这个没有说绝对的谁好谁坏。
 

class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {static getDerivedStateFromError(e: any) {console.error('getDerivedStateFromError: ', e);// 这里可以做错误上报return { hasError: true };}constructor(props: ErrorBoundaryProps) {super(props);this.state = { hasError: false };}render() {if (this.state.hasError) {return '这是错误发生时的UI';}return this.props.children;}
}export default ErrorBoundary;

网络请求错误

静态资源加载失败

静态资源包括js,css,image,字体文件等

如何监控静态资源加载失败呢?

<!DOCTYPE html>
<html lang="en"><head><script>window.addEventListener('error', function (e) {console.log('error1:', e)})</script></head><body><img id="image" src="./404.png" alt=""><script>document.getElementsByTagName('img')[0].addEventListener('error', function (e) {console.log('image error', e)})</script>
</body></html>

输入结果

可以看到, window.addEventListener('error')并没有捕获到错误,这是为什么?
原来静态资源的错误,并不会冒泡到window,只能在事件捕获阶段拿到,调整代码,第3个参数改为true

    window.addEventListener('error', function (e) {console.log('error1:', e)},true)

成功拿到错误

 Script error,拿不到错误信息?

Script error. 也被称为跨域错误,当网站请求并且执行一个非本域名下的脚本的时候,如果跨域脚本发生错误,就有可能抛出这个错误。由于项目中,我们的脚本都是放在 CDN 上的,因此这种错误最为常见。

出于安全考虑,浏览器会刻意隐藏其他域的JS文件抛出的具体错误信息,这样做可以有效避免敏感信息无意中被不受控制的第三方脚本捕获。因此,浏览器只允许同域下的脚本捕获具体错误信息,而其他脚本只知道发生了一个错误,但无法获知错误的具体内容
可以参考 Script error · Issue #3 · BetterJS/badjs-report · GitHub


捕获AJAX 错误

不论是XHR还是fetch,我们都是通过函数劫持的办法实现错误监控的

XHR

const trackXHR = () => {const XHR = window.XMLHttpRequest;const originSend = XHR.prototype.send;XHR.prototype.send = function () {const errorHandler = (event) => {try {if (event && event.currentTarget && event.currentTarget.status !== 200) {const log = {status: this.status,type: 'xhr',// 其他要上报的数据}// 这里上报console.log('log----', log)}} catch {// SDK error}}// 重写load、error、abort方法,来处理请求结束时的逻辑,但是为什么不用函数拦截呢?// 因为用户有时候可能不会去调用 xhr.onload、xhr.error、xhr.abort 方法,如果都没有调用,拦截函数也不会执行,// 所以这里可以用 addEventListener 的方式this.addEventListener('load', errorHandler, false)this.addEventListener('error', errorHandler, false)this.addEventListener('abort', errorHandler, false)return originSend.apply(this, arguments)}// 兼容一些特殊场景,有些场景 XHR 对象不存在responseURL属性,这里记录下来const originOpen = XHR.prototype.openXHR.prototype.open = function (methods, url, async) {this.ajaxURL = url;return originOpen.apply(this, arguments)}
}

捕获 fetch 错误

const trackFetch = () => {if (!window.fetch) return;const originFetch = window.fetch;window.fetch = function () {return originFetch.apply(this, arguments).then(res => {if (res.ok) {return res;}// 响应不为 ok 时,比如接口 400 404,500,上报错误信息}).catch(err=>{// 如果代码有bug,或者请求发生了跨域错误,则会执行这里// 在这里上报错误信息// 并且抛出错误,让错误能被其他地方捕获到throw err })}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/107937.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux CentOS7修改命令行提示符

在CentOS操作系统中&#xff0c;命令和文件是我们与计算机进行交互的重要方式之一。有时候我们可能需要对某些命令、变量或文件进行修改&#xff0c;以满足特定的需求或提高工作效率。 本人在文章《Linux CentOS7命令及命令行》中对命令行提示符的修改作了初步介绍&#xff0c…

微服务08-认识和使用SpringAMQP

1.AMQP的认识 1.1 介绍 AMQP是什么&#xff1f;看完你就知道了_hello_读书就是赚钱的博客-CSDN博客_amqp 好处&#xff1a; 什么connection&#xff1a;消息队列的连接、channel&#xff1a;服务发送接收消息的通道、Queue&#xff1a;消息队列——>这些你都不需要自己编写…

【计算机视觉 | 目标检测】干货:目标检测常见算法介绍合集(二)

文章目录 十六、EfficientDet十七、Deformable DETR十八、YOLOX十九、Sparse R-CNN二十、Contour Proposal Network二十一、VarifocalNet二十二、Libra R-CNN二十三、Stand-Alone Self Attention二十四、ThunderNet二十五、Hierarchical Transferability Calibration Network二…

【杂记】git管理工具的相关应用

这里记录一些用git管理工具进行开发的命令&#xff0c;便于自己查看&#xff0c;我认为下面两篇博客写的很详细&#xff0c;但是为了自己方便查看&#xff0c;所以自己写了一些命令供自己进一步理解。gitee相对git来说更方便一些&#xff08;毕竟国内的不用担心墙&#xff09;&…

UMA 2 - Unity Multipurpose Avatar☀️六.Advanced Occlusion高级遮挡功能解决皮肤服饰穿模

文章目录 🟥 本节功能效果展示🟧 基础项目配置🟨 本节项目配置🟩 配置MeshHideAsset1️⃣ 创建MeshHideAsset2️⃣ 配置SlotDataAsset3️⃣ 配置遮挡信息🟦 将 MeshHideAsset 配置到 Recipe🟥 本节功能效果展示 未遮挡前的穿模问题: 遮挡后效果:

SpringMVC_拦截器

4.拦截器 4.1拦截器概述 概述&#xff1a;一种动态拦截方法调用的机制&#xff0c;在SpringMVC中动态拦截控制器方法的执行实际开发中&#xff0c;静态资源&#xff08;HTML/CSS&#xff09;不需要交给框架处理&#xff0c;需要拦截的是动态资源 4.2图示 图示 4.3案例实现 …

闭包的理解

1.什么是闭包&#xff1f; 变量的私有化。一个函数内的变量,随着函数的执行完毕,对于的变量也会随着销毁,闭包可以让变量在函数执行完毕之后不必销毁,通常将这个变量通过匿名函数的形式return出去,这个变量只能被访问,不能被修改。 2.证明变量执行玩被销毁 (1)函数体没有被包…

朋友圈大佬都去读研了,这份备考书单我码住了

作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

day3_C++

day3_C 思维导图用C的类完成数据结构 栈的相关操作用C的类完成数据结构 循环队列的相关操作 思维导图 用C的类完成数据结构 栈的相关操作 stack.h #ifndef STACK_H #define STACK_H#include <iostream> #include <cstring>using namespace std;typedef int datat…

【数据结构】堆的创建

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

jmeter采集ELK平台海量业务日志( 采用Scroll)

由于性能测试需要&#xff0c;需采集某业务系统海量日志&#xff08;百万以上&#xff09;来使用。但Elasticsearch的结果分页size单次最大为10000&#xff08;运维同事为保证ES安全&#xff09;。为了能够快速采集ELK平台业务日志&#xff0c;可以使用以下2种方式采集&#xf…

spring spring-boot spring-cloud spring-cloud-alibaba之间版本对应关系

spring 版本与 jdk 的对应关系 https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions 从 spring 6.0 开始使用 jdk 17 进行编译 对应的相关 servlet 容器&#xff08;tomcat、undertow、jetty等&#xff09;的 servlet 规范转移到 eclipse&…