这是我参与「第四届青训营」笔记创作活动的的第 10 天
JavaScript 异常
页面中的所有 JavaScript 异常都会被发送到 window.onerror 这个事件上面。除了可以获取到 error 对象,还可以拿到发生异常的 url、行数、列数等。
window.onerror = (msg, url, row, col, error) => {
console.log('JS 异常')
console.log('Error message', msg)
console.log('Error url', url)
console.log('Error position', `${row}:${col}`)
console.log(error)
}
有意思的是,这个 onerror 不仅可以捕获运行过程中的 Error,还可以捕获 JavaScript 的语法错误。 但是要注意只有在设置了监听之后的 JavaScript 错误才能被捕获到,包括语法错误。因此如果要捕获语法错误,一定要保证这段捕获的代码没有错误并且是整个页面中最先加载的 JavaScript,否则语法错误会先于设置监听的时候抛出,这样就捕获不到了。
资源异常
捕获资源加载的异常,使用 window.addEventListener('error', callback)。 需要注意的是,这个监听也会捕获到上面讲到的 window.onerror 的异常,因此需要对 JavaScript 异常进行一下过滤:
window.addEventListener(
'error',
e => {
if (isJsError(e)) {
return
}
console.log('资源加载错误', e)
},
true,
)
function isJsError(e) {
const target = e.target || e.srcElement
const isElementTarget =
target instanceof HTMLScriptElement ||
target instanceof HTMLLinkElement ||
target instanceof HTMLImageElement
return !isElementTarget || e instanceof ErrorEvent
}
未处理 Promise 异常
页面中的所有未处理的 Rejected Promise 都会被发送到 unhandledrejection 这个事件中:
window.addEventListener('unhandledrejection', e => {
console.log('未处理 Promise 异常', e)
})
fetch 异常
现代浏览器中提供了一个基于 Promise 的 fetch API,但是值得注意的是,fetch 虽然基于 Promise,但如果失败并不会被上面这种 Rejected Promise 处理。如果要处理 fetch 失败的异常,可以通过对全局 fetch 添加一个猴子补丁来实现:
const originFetch = window.fetch
window.fetch = function (...args) {
if (!originFetch) {
return
}
return originFetch.apply(this, args).catch(err => {
console.log('fetch 异常', err)
})
}
白屏异常
白屏异常不是个异常的种类,而是指那些触发的异常导致整个页面无法正常加载,用户看到的一直是白屏的异常。
要监控白屏异常,可以通过延时检查关键元素中是否存在内容来实现:
let monitorWhiteScreenNode = document.querySelector('#app');
if (monitorWhiteScreenNode) {
setTimeout(() => {
try {
if (!(/\w/.test(monitorWhiteScreenNode!.innerHTML))) {
// 重要节点没有内容
reportWhiteScreen({ detail: monitorWhiteScreenNode!.outerHTML });
}
} catch (err) {
}
}, 2000);
}