add file:前端错误监控
This commit is contained in:
		
							parent
							
								
									ffb084fd9a
								
							
						
					
					
						commit
						e3566d9cc5
					
				
							
								
								
									
										181
									
								
								06-前端基础/15-前端错误监控.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								06-前端基础/15-前端错误监控.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,181 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 前言
 | 
			
		||||
 | 
			
		||||
错误监控包含的内容是:
 | 
			
		||||
 | 
			
		||||
- 前端错误的分类
 | 
			
		||||
 | 
			
		||||
- 每种错误的捕获方式
 | 
			
		||||
 | 
			
		||||
- 上报错误的基本原理
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
面试时,可能有两种问法:
 | 
			
		||||
 | 
			
		||||
- 如何监测 js 错误?(开门见山的方式)
 | 
			
		||||
 | 
			
		||||
- 如何保证**产品质量**?(其实问的也是错误监控)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 前端错误的分类
 | 
			
		||||
 | 
			
		||||
包括两种:
 | 
			
		||||
 | 
			
		||||
- 即时运行错误(代码错误)
 | 
			
		||||
 | 
			
		||||
- 资源加载错误
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 每种错误的捕获方式
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 即时运行错误的捕获方式
 | 
			
		||||
 | 
			
		||||
**方式1**:try ... catch。
 | 
			
		||||
 | 
			
		||||
这种方式要部署在代码中。
 | 
			
		||||
 | 
			
		||||
**方式2:**`window.onerror`函数。这个函数是全局的。
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
	window.onerror = function(message, source, lineno, colno, error) { ... }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
参数解释:
 | 
			
		||||
 | 
			
		||||
- mesage为异常基本信息
 | 
			
		||||
 | 
			
		||||
- source为发生异常Javascript文件的url
 | 
			
		||||
 | 
			
		||||
- lineno为发生错误的行号
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
方式二中的`window.onerror`是属于DOM0的写法,我们也可以用DOM2的写法:`window.addEventListener("error", fn);`也可以。
 | 
			
		||||
 | 
			
		||||
**问题延伸:**
 | 
			
		||||
 | 
			
		||||
`window.onerror`默认无法捕获**跨域**的js运行错误。捕获出来的信息如下:(基本属于无效信息)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
比如说,我们的代码想引入B网站的`b.js`文件,怎么捕获它的异常呢?
 | 
			
		||||
 | 
			
		||||
**解决办法**:在方法二的基础之上,做如下操作:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(1)在静态资源服务器或者CDN的HTTP头中加 如下 response header,表示允许跨域:(或者世界给静态资源`b.js`加这个 response header)
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
	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/)
 | 
			
		||||
 | 
			
		||||
### 资源加载错误的捕获方式
 | 
			
		||||
 | 
			
		||||
上面的window.onerror只能捕获即时运行错误,无法捕获资源加载错误。原理是:资源加载错误,并不会向上冒泡,object.onerror捕获后就会终止(不会冒泡给window),所以window.onerror并不能捕获资源加载错误。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**方式1:**object.onerror。img标签、script标签等节点都可以添加onerror事件,用来捕获资源加载的错误。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**方式2:**performance.getEntries。可以获取所有已加载资源的加载时长,通过这种方式,可以间接的拿到没有加载的资源错误。
 | 
			
		||||
 | 
			
		||||
举例:
 | 
			
		||||
 | 
			
		||||
浏览器打开一个网站,在Console控制台下,输入:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
	performance.getEntries().forEach(function(item){console.log(item.name)})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
或者输入:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
	performance.getEntries().forEach(item=>{console.log(item.name)})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
上面这个api,返回的是数组,既然是数组,就可以用forEach遍历。打印出来的资源就是**已经成功加载**的资源。;
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
再输入`document.getElementsByTagName('img')`,就会显示出所有**需要加载**的的img集合。
 | 
			
		||||
 | 
			
		||||
于是,`document.getElementsByTagName('img')`获取的资源数组减去通过`performance.getEntries()`获取的资源数组,剩下的就是没有成功加载的,这种方式可以间接捕获到资源加载错误。
 | 
			
		||||
 | 
			
		||||
这种方式非常有用,一定要记住。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**方式3;**Error事件捕获。
 | 
			
		||||
 | 
			
		||||
源加载错误,虽然会阻止冒泡,但是不会阻止捕获。我们可以在捕获阶段绑定error事件。例如:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**总结:**如果我们能回答出后面的两种方式,面试官对我们的印象会大大增加。既可以体现出我们对错误监控的了解,还可以体现出我们对事件模型的掌握。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
参考链接:
 | 
			
		||||
 | 
			
		||||
- [前端错误监控原理与实战](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>
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
打开浏览器,效果如下:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
上图中,红色那一栏表明,我的请求已经发出去了。点进去看看:
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
这种方式,不需要借助第三方的库,一行代码即可搞定。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user