前端线上项目接入Sentry监控后解决的几类问题
一. UnhandledRejection
- 监控报错如下:
- 发生的原因:
方法封装使用了 Promise.reject() 方法,但在调用的时候只写了 .then(()=>{}) 回调,没有写 .catch(()=>{})
- 解决思路:
-
补全catch回调逻辑(但由于此类代码改动过多,所以考虑第二种方式)
-
全局拦截报错
window.addEventListener('unhandledrejection', function browserRejectionHandler(event) {
event && event.preventDefault()
})
- 建议:
-
以上是解决问题的方案,但在常规写法中,尽量还是把then和catch的回调都写上,这样的代码逻辑比较正向。
-
或者,在公用异步方法封装的时候,不使用Promise.rejcet()这个API,全部使用resolve()方法,通过resolve()方法的不同状态码进行判断,这样就可以不用写catch拦截报错,提高了编码效率,毕竟每个请求调用后在.then()方法中还要判断status,可以协同之前reject的情况顺便处理了,网络超时或特殊的情况,可以全局弹窗提示,这样就不用写.catch()回调了。
二. Cannot read properties of null (reading 'getBoundingClientRect')
- 监控报错如下:
- 发生的原因:
render方法还没有完全渲染出节点,就去获取Dom和调用方法,拿到了 null
var render = new dagreD3.render()
const Group = svg.append('g')
// d3.select(g)有时候会有找不到g标签的情况,所以使用ref传入
.attr('height', this.svgH)
.attr('id', 'g_chart')
render(Group, g) // 渲染节点
const ele_g = document.getElementById('g_chart').getBoundingClientRect()
const ele_svg = document.getElementById('piercethrough').getBoundingClientRect()
const computNum = 0 - (ele_g.width / 2 - ele_svg.width / 2)
- 解决思路:
将 render 方法后的逻辑 放到 this.$nextTick(()=>{}) 中,在节点渲染后,再执行获取操作
三. Cannot read properties of null (reading 'getAttribute')
-
监控报错如下:
-
发生的原因:
此报错关联了 echarts 这个库,在屏幕缩放调用了 resize 回调进行重绘,执行顺序的问题
- 解决思路:
下次事件循环再调用重绘
四. Unhandled Network Error
- 监控报错如下:
- 发生的原因:
因为代码中请求超时会在抛出了一个错误
- 解决思路:
把这个打印去掉,有需要的话,弹窗提示超时即可
五. UnhandledRejection: Non-Error promise rejection captured with value: 20002
这个错误信息表示在 Promise 中发生了未处理的 rejection,而且 rejection 的值不是一个 Error 对象,而是一个值为 20002 的非 Error 对象。
可以通过以下方式解决:
- 在代码中使用 try/catch 捕获异常并处理。
- 使用
catch()
方法或Promise.reject()
显式地捕获和处理 Promise rejection,并确保返回一个 Error 对象。 - 确认该值为非 Error 对象是否符合预期,如果不符合,则需要检查代码逻辑是否有问题。
例如,在 Promise 中返回一个字符串,就会引发类似的错误:
async function fetchData() {
const data = await fetch('https://example.com/api/data');
return '20002'; // 返回一个字符串
}
fetchData().then(response => {
console.log(response);
}).catch(error => {
console.error(error); // UnhandledRejection: Non-Error promise rejection captured with value: 20002
});
正确的做法是返回一个 Error 对象:
async function fetchData() {
const data = await fetch('https://example.com/api/data');
return new Error('500 Internal Server Error'); // 返回一个 Error 对象
}
fetchData().then(response => {
console.log(response);
}).catch(error => {
console.error(error); // 500 Internal Server Error
console.log(error.message) // 500 Internal Server Error
});
这样就能够避免上述错误。
六. Unhandled Cannot read properties of undefined (reading 'catch')
例如,在下面的代码中,由于 getUserData()
函数未返回任何值,导致无法使用 .catch()
方法,进而触发了上述错误:
async function getUserData() {
const response = await fetch('https://example.com/api/user');
// return undefined;
}
getUserData()
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error); // Unhandled TypeError: Cannot read properties of undefined (reading 'catch')
});
解决方案是确保 getUserData()
函数返回一个值并处理 Promise rejection:
async function getUserData() {
const response = await fetch('https://example.com/api/user');
return response.json();
}
getUserData()
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
这样就可以避免上述错误。
七. Cannot read properties of null (reading 'clientHeight')
-
sentry 报错概览
-
sentry 报错细节
-
发生原因:
- 因为在null值上访问了他的 clientHeight 属性
-
分析场景
- 可能是当前页面没有加载完成,就去点击路由跳转,导致页面切换,方法执行报错
- 就是当前节点没有访问到,可能是在 created 生命周期访问了节点
-
解决方式:
- 加个判断,拿到当前节点之后再进行链式访问
- 加个判断,拿到当前节点之后再进行链式访问
转载自:https://juejin.cn/post/7222862599841546299