异常捕获方法
1.try catch
检测一段代码是否具有异常,常用如下写法:1
2
3
4
5
6
7try {
var a = 1;
var b = a + c;
} catch (e) {
// 捕获处理
console.log(e); // ReferenceError: c is not defined
}
使用该方法不至于让页面挂掉,需要包裹要捕获的代码,易造成臃肿,不适用于整个项目的异常捕获。
2.window.onerror
提供了全局监听异常功能:1
2
3
4
5
6
7
8window.onerror = function(errorMessage, scriptURI, lineNo, columnNo, error) {
console.log('errorMessage: ' + errorMessage); // 异常信息
console.log('scriptURI: ' + scriptURI); // 异常文件路径
console.log('lineNo: ' + lineNo); // 异常行号
console.log('columnNo: ' + columnNo); // 异常列号
console.log('error: ' + error); // 异常堆栈信息
};
console.log(a);
异常捕获出现的问题
1.Script error
1 | <!-- http://localhost:3031/ --> |
跨域请求的时候,window.onerror是无法正常捕获信息的,统一返回Script error,解决方法即script属性配置crossorigin=”anonymous”,并且服务器添加Access-Control-Allow-Origin,即如下:1
<script src="http://cdn.xxx.com/index.js" crossorigin="anonymous"></script>
一般情况下CDN网站将Access-Control-Allow-Origin配置为*。即所有域都可以访问。
2.sourceMap
解决跨域或者将脚本放在同域下,压缩代码发布,暴露压缩代码无法找到原始报错位置问题。
使用webpack将代码打包压缩成bundle.js1
2
3
4
5
6
7
8
9
10
11// webpack.config.js
var path = require('path');
// webpack 4.1.1
module.exports = {
mode: 'development',
entry: './client/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'client')
}
}
解决方案:利用webpack打包压缩生成对应脚本的map文件追踪,在webpack中开启source-map功能1
2
3
4
5
6
7module.exports = {
...
devtool: '#source-map',
...
}
// 打包压缩文件会有如下注释:
// # sourceMappingURL=bundle.js.map
3.MVVM框架
MVVM框架中不能使用window.onerror来捕获异常,因为异常信息被框架的自身异常机制捕获了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// Vue中处理
Vue.config.errorHandler = function (err, vm, info) {
let {
message, // 异常信息
name, // 异常名称
script, // 异常脚本url
line, // 异常行号
column, // 异常列号
stack // 异常堆栈信息
} = err;
// vm为抛出异常的 Vue 实例
// info为 Vue 特定的错误信息,比如错误所在的生命周期钩子
}
// React中处理
class ErrorBoundary extends React.Component{}
// 使用组件
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
异常上报
常见处理压缩文件异常上报的方法:
1.提交异常
以window.onerror为例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16window.onerror = function(errorMessage, scriptURI, lineNo, columnNo, error) {
// 构建错误对象
var errorObj = {
errorMessage: errorMessage || null,
scriptURI: scriptURI || null,
lineNo: lineNo || null,
columnNo: columnNo || null,
stack: error && error.stack ? error.stack : null
};
if (XMLHttpRequest) {
var xhr = new XMLHttpRequest();
xhr.open('post', '/middleware/errorMsg', true); // 上报给node中间层处理
xhr.setRequestHeader('Content-Type', 'application/json'); // 设置请求头
xhr.send(JSON.stringify(errorObj)); // 发送参数
}
}
2.scourceMap解析
source-map格式的文件是一种数据类型,浏览器或者Node的情况下使用”source-map”的插件。通过require加载该插件,使用服务器解析。
3.异常上报注意问题
- 针对跨域脚本,Safari出现script error的处理。
- 脚本压缩后,通过sourcemap还原错误信息。
- 一些异步回调错误有时候onerror无法捕获,需要使用try catch。
- 框架抛出的错误onerror无法捕获,可以通过框架自带的错误处理上报。
- window.onerror这样的异常捕获不能捕获promise的异常错误信息。
- 访问量较大应对异常做信息过滤和采样,设置调控开关,服务器也可以对相似异常进行过滤,不重复存储以免挂掉服务器。
参考文章:
谈谈前端异常捕获于上报
如有错误,烦请指正,谢谢!