Web/14-前端面试/11-前端错误监控.md

186 lines
4.9 KiB
JavaScript
Raw Normal View History

2018-03-11 21:06:34 +08:00
## 前言
错误监控包含的内容是
- 前端错误的分类
- 每种错误的捕获方式
- 上报错误的基本原理
面试时可能有两种问法
- 如何监测 js 错误开门见山的方式
- 如何保证**产品质量**其实问的也是错误监控
## 前端错误的分类
包括两种
- 即时运行错误代码错误
- 资源加载错误
## 每种错误的捕获方式
### 即时运行错误的捕获方式
**方式1**try ... catch
这种方式要部署在代码中
**方式2**`window.onerror`函数这个函数是全局的
```
2018-03-12 21:01:35 +08:00
window.onerror = function(msg, url, row, col, error) { ... }
2018-03-11 21:06:34 +08:00
```
参数解释
2018-03-12 21:01:35 +08:00
- msg为异常基本信息
2018-03-11 21:06:34 +08:00
- source为发生异常Javascript文件的url
2018-03-12 21:01:35 +08:00
- row为发生错误的行号
2018-03-11 21:06:34 +08:00
方式二中的`window.onerror`是属于DOM0的写法我们也可以用DOM2的写法`window.addEventListener("error", fn);`也可以
2018-03-12 21:01:35 +08:00
**问题延伸1**
2018-03-11 21:06:34 +08:00
`window.onerror`默认无法捕获**跨域**的js运行错误捕获出来的信息如下基本属于无效信息
比如说我们的代码想引入B网站的`b.js`文件怎么捕获它的异常呢
**解决办法**在方法二的基础之上做如下操作
2018-03-12 21:01:35 +08:00
1`b.js`文件里加入如下 response header表示允许跨域或者世界给静态资源`b.js`加这个 response header
2018-03-11 21:06:34 +08:00
```
Access-Control-Allow-Origin: *
```
2引入第三方的文件`b.js``<script>`标签中增加`crossorigin`属性
参考链接
- [window.onerror的总结](https://www.jianshu.com/p/315ffe6797b8)
- [前端代码异常日志收集与监控](http://www.cnblogs.com/hustskyking/archive/2015/08/20/fe-monitor.html)
- [捕获页面中全局Javascript异常](https://foio.github.io/javascript-global-exceptions/)
2018-03-12 21:01:35 +08:00
**问题延伸2**
只靠方式二中的`window.onerror`是不够的因为我们无法获取文件名是什么不知道哪里出了错误解决办法**堆栈**信息作为msg打印出来堆栈里很详细
2018-03-11 21:06:34 +08:00
### 资源加载错误的捕获方式
上面的window.onerror只能捕获即时运行错误无法捕获资源加载错误原理是资源加载错误并不会向上冒泡object.onerror捕获后就会终止不会冒泡给window所以window.onerror并不能捕获资源加载错误
2018-03-12 21:01:35 +08:00
**方式1**object.onerrorimg标签script标签等节点都可以添加onerror事件用来捕获资源加载的错误
2018-03-11 21:06:34 +08:00
2018-03-12 21:01:35 +08:00
**方式2**performance.getEntries可以获取所有已加载资源的加载时长通过这种方式可以间接的拿到没有加载的资源错误
2018-03-11 21:06:34 +08:00
举例
浏览器打开一个网站在Console控制台下输入
```
performance.getEntries().forEach(function(item){console.log(item.name)})
```
或者输入
```
performance.getEntries().forEach(item=>{console.log(item.name)})
```
上面这个api返回的是数组既然是数组就可以用forEach遍历打印出来的资源就是**已经成功加载**的资源
![](http://img.smyhvae.com/20180311_2030.png)
再输入`document.getElementsByTagName('img')`就会显示出所有**需要加载**的的img集合
于是`document.getElementsByTagName('img')`获取的资源数组减去通过`performance.getEntries()`获取的资源数组剩下的就是没有成功加载的这种方式可以间接捕获到资源加载错误
这种方式非常有用一定要记住
**方式3**Error事件捕获
源加载错误虽然会阻止冒泡但是不会阻止捕获我们可以在捕获阶段绑定error事件例如
![](http://img.smyhvae.com/20180311_2040.png)
**总结**如果我们能回答出后面的两种方式面试官对我们的印象会大大增加既可以体现出我们对错误监控的了解还可以体现出我们对事件模型的掌握
参考链接
- [前端错误监控原理与实战](http://www.cnblogs.com/gaoning/p/7928497.html) (作者的这篇文章参考了面试内容)
## 错误上报的两种方式
**方式一**采用Ajax通信的方式上报此方式虽然可以上报错误但是我们并不采用这种方式
**方式二**利用Image对象上报推荐网站的监控体系都是采用的这种方式
方式二的实现方式如下
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//通过Image对象进行错误上报
(new Image()).src = 'http://smyhvae.com/myPath?badjs=msg'; // myPath表示上报的路径我要上报到哪里去。后面的内容是自己加的参数。
</script>
</body>
</html>
```
打开浏览器效果如下
![](http://img.smyhvae.com/20180311_2055.png)
上图中红色那一栏表明我的请求已经发出去了点进去看看
![](http://img.smyhvae.com/20180311_2057.png)
这种方式不需要借助第三方的库一行代码即可搞定