最近在研究前端监控相关的内容,整理下前端相关的错误,记录下
一、常见的前端异常
- 语法错误,编译阶段就可以发现的错误
- JS运行异常,属性、方法缺失,浏览器不支持等
- 加载静态资源错误
- 请求接口异常:Ajax、Fetch、websocket
- Promise处理错误
- 框架错误:React、Vue、Angular
- 获取压缩、混淆后的代码错误
二、监控流程
graph TD
监控错误:JsError/Promise --> 收集错误:整理错误信息数据结构 --> 上报错误:上传错误信息到数据库,控制重复上传频率 --> 分析错误:错误类型,错误出现的频率 --> 错误报警:推送邮件/短信/微信/语音等 --> 定位错误:错误发生的代码位置 --> 解决错误:配置错误处理人等信息
三、JS错误
类型 | 含义 | 说明 |
---|---|---|
Error | 错误基类 | new Error(),有两个属性name和message,name错误类型、message错误信息 |
SyntaxError | 语法错误 | 语法错误 |
ReferenceError | 引用错误 | 常见于引用了一个不存在的变量: let a = undefinedVariable; |
RangeError | 有效范围 | 错误数值变量或参数超出了其有效范围。 常见于 1.创建一个负长度数组 2.Number对象的方法参数超出范围:let b = new Array(-1) |
TypeError | 类型错误 | 常见于变量或参数不属于有效类型 let foo = 3;foo(); |
URIErrorURL | 处理函数错误 | 使用全局URL处理函数错误,比如 decodeURIComponent('%'); |
EvalError | Eval错误 | 常常出现在TypeError |
1、Error
new Error("test")
Error的属性:name, message。
2、SyntaxError
语法错误:该错误在编译阶段就可以发现
// console.log少了一个小括号,代码编译出现语法错误
console.log(testFinally()
该错误可以在编译阶段抛出,所以不做监控
3、ReferenceError
引用错误:当使用未定义的变量时,就会抛出该错误,该错误大多数在编译阶段就可以检测出来。
4、TypeError
类型错误:值类型非预期的错误。该错误类型是监控中出现的大头,如接口返回数据,值为undefined
// data 来自接口返回,值为undefined或null,而undefined和null没有length属性
data.length
console.lg("this is a TypeError")
自行定义TypeError类型错误:自行定义一些类型导致的错误
function add(a, b) {
if(typeof a !== 'number'){
throw TypeError(`The first argument must be a number`)
}
if(typeof b !== 'number'){
throw TypeError(`The second argument must be a number`)
}
return a + b
}
add('string', 1);
5、RangeError
数组长度错误:当数组的长度超过计算机允许的最大值、小于数组长度的最小值,就会出现该错误
6、URIError
URL解析或编码错误:
- encodeURI
- decodeURI
- decodeURIComponent
- encodeURIComponent
7、EvalError
EvalError该类错误常常表现为TypeError,如下图
let e = new eval();
8、自定义Error类
可以在Error类型的基础上扩展错误类型,自定义类型
class InvalidCallError extends Error {
name: "InvalidCallError",
constructor(message){
super()
this.message = message
}
}
const error = new InvalidCallError("this is a InvalidCallError")
四、获取资源加载错误
资源错误指:js、图片、css等静态资源加载异常
例如:有一个不存在的图片路径404了。我们依然可以监听该错误,通过error,target字段判断是否为资源类型
<img src="http://localhost:9000/index.png" />
window.addEventListener('error', function(event) {
console.log("addEventListener", event)
}, true)
五、Promise异常
Promise相关的错误作为一个单独的错误类型,可以获取对应的错误信息
Promise.reject("test")
window.addEventListener('unhandledrejection', function(event) {
console.log("unhandledrejection", event)
}, true)
六、React错误捕获
React暴露了方法来监听错误,封装如下高阶组件,在componentDidCatch
中处理捕获的错误
import * as React from 'react';
class ErrorListening extends React.Component {
constructor(props) {
super(props);
}
componentDidCatch(error, info) {
console.log("error", error)
}
}
在项目中使用
import React from "react";
<ErrorListening>
<App />
</ErrorListening>
七、监听前端报错信息
1、window.onerror
window.onerror = function(message, source, lineno, colno, error) { ... }
message
:错误信息(字符串)。可用于 HTMLonerror=""
处理程序中的event
。source
:发生错误的脚本 URL(字符串)lineno
:发生错误的行号(数字)colno
:发生错误的列号(数字)error
:Error 对象(对象)
若该函数返回true
,则阻止执行默认事件处理函数。
console.log("test", a)
window.onerror = function(message, source, lineno, colno, error) {
console.error("message", message)
console.error("source", source)
console.error("lineno", lineno)
console.error("colno", colno)
console.error("error", error)
console.error("error.name", error.name)
console.error("error.message", error.message)
}
2、addEventListener
window.addEventListener('error', function(event) {
console.log("addEventListener", event)
})
同一个错误,我们可以发现addEventListener拿到的信息更多
两者的区别是:
- 两者都能监听到错误信息,
window.onerror
获取的是msg, url, lineNo, columnNo, error等一系列参数,而addEventListener
获取的是events事件,包含了上面的信息和其他的一些信息,更全一些 addEventListener
可以监听到资源错误信息,而window.onerror不能