前端错误监控
前端错误监控
常见错误类型
| 错误 | 解释 | 示例 |
|---|---|---|
| SyntaxError | 解析时发生语法错误 | const x |
| TypeError | 值不是所期待的类型 | const person = 1; person.name |
| ReferenceError | 引用未声明的变量 | x |
| RangeError | 一个值不在其所允许的范围中 | new Array(-1) |
| ResourceError | 资源加载错误 | new Image().src = ‘/remote/null.jpg’ |
| HttpError | http 请求错误 | fetch(‘/remote/null’) |
如何捕获错误
try/catch
能够捕获常规运行时错误,语法错误和异步错误无法捕获
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 常规运行时错误,可以捕获 ✅
try {
console.log(notdefined);
} catch(e) {
console.log('捕获到异常:', e);
}
// 语法错误,不能捕获 ❌
try {
const notdefined,
} catch(e) {
console.log('捕获到异常:', e);
}
// 异步错误,不能捕获 ❌
try {
setTimeout(() => {
console.log(notdefined);
}, 0)
} catch(e) {
console.log('捕获到异常:',e);
}
window.onerror
混合事件 GlobalEventHandlers 的 onerror 属性是用于处理 error 的事件 Error 事件的事件处理程序,在各种目标对象的不同类型错误被触发:
- 当 JavaScript 运行时错误(包括语法错误)发生时,window 会触发一个 ErrorEvent 接口的 error 事件,并执行 window.onerror()。
- 当一项资源(如<img>或<script>)加载失败,加载资源的元素会触发一个 Event 接口的 error 事件,并执行该元素上的 onerror() 处理函数。这些 error 事件不会向上冒泡到 window,不过(至少在 Firefox 中)能被单一的 window.addEventListener 捕获。
1
window.onerror = function(message, source, lineno, colno, error) { ... }
函数参数:
- message:错误信息(字符串)。可用于 HTML onerror=”“处理程序中的 event。
- source:发生错误的脚本 URL(字符串)
- lineno:发生错误的行号(数字)
- colno:发生错误的列号(数字)
- error:Error 对象(对象)
若该函数返回 true,则阻止执行默认事件处理函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 常规运行时错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
console.log(notdefined);
// 语法错误,不能捕获 ❌
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
const notdefined,
// 异步错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
setTimeout(() => {
console.log(notdefined);
}, 0)
// 资源错误,不能捕获 ❌
<script>
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
return true;
}
</script>
<img src="https://unknown/image/null.png">
window.addEventListener
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 图片、script、css加载错误,都能被捕获 ✅
<script>
window.addEventListener(
"error",
(error) => {
console.log("捕获到异常:", error)
},
true
)
</script>
<img src="https://unknown/image/null.png" />
<script src="https://unknown/foundnull.js"></script>
<link href="https://unknown/foundnull.css" rel="stylesheet" />
// new Image错误,不能捕获 ❌
<script>
window.addEventListener(
"error",
(error) => {
console.log("捕获到异常:", error)
},
true
)
</script>
<script>
new Image().src = "https://unknown/image/null.png"
</script>
// fetch错误,不能捕获 ❌
<script>
window.addEventListener(
"error",
(error) => {
console.log("捕获到异常:", error)
},
true
)
</script>
<script>
fetch("https://unknown/test")
</script>
异步错误
如果使用 try/catch 能捕获 await 的错误 普通 Promise 错误 使用 catch
全局捕获错误 - unhandledrejection
1
2
3
4
5
// 全局统一处理Promise
window.addEventListener("unhandledrejection", function (e) {
console.log("捕获到异常:", e)
})
fetch("https://unknown/test")
Vue 的错误
vue 的错误会被 vue 自动捕获,并且抛给 Vue.config.errorHandler。
1
2
3
4
5
6
7
8
/**
* 全局捕获Vue错误,直接扔出给onerror处理
*/
Vue.config.errorHandler = function (err) {
setTimeout(() => {
throw err
})
}
React 错误
react 通过 componentDidCatch,声明一个错误边界的组件
数据上报接口
使用 1*1 像素的 gif 图片进行上报,有以下几点好处
- 不会阻塞页面渲染
- 图片天然跨域
- 不会携带 Cookie
- 不需等待服务器返回数据
- gif 图片所需流量最小
但数据太大,最好还是用 post
本文由作者按照 CC BY 4.0 进行授权