前端开发之异常捕获技巧
作为⼀个前端开发⼈员,每次看到浏览器控制台信息⾥⾯红通通的报错信息是不是都很紧张......不要怕,下⾯我们就来讨论⼀下前端的异常捕获。
异常捕获,相对于其他知识点可能没那么被重视,特别是对于前端程序员。但不得不说,这⼜是⼀个不得不⾯对的知识点。
为什么要捕获异常
⾸先,我们为什么要进⾏异常捕获和上报呢?
正所谓百密⼀疏,⽤程序员的话来说就是:天下不存在没有bug的程序(不接受反驳 )。即使经过各种测试,还是会存在⼗分隐蔽的bug,这种不可预见的问题只有通过完善的监控机制才能有效的减少其带来的损失。因此,对于最接近⽤户的前端来说,为了能远程定位问题、增强⽤户体验,异常的捕获和上报⾄关重要。
⽬前市⾯上已经有⼀些⾮常完善的前端监控系统存在,如Fundebug、Bugsnag等,虽然这些已经能做到帮我们实时监控⽣产环境的异常,但是如果我们不了解异常是如何产⽣的,⼜怎么能得⼼应⼿的定位并处理问题呢?
对于JS⽽⾔,我们⾯对的仅仅只是异常,异常的出现不会直接导致JS引擎崩溃,最多只是终⽌当前代码的执⾏。下⾯来解释⼀下这句话:
<script>
error // 没定义过的变量,此处会报错
console.log('永远不会执⾏');
</script>
<script>
console.log('我继续执⾏')
</script>
异常捕获分类
这⾥我做了⼀个脑图归纳⼀些前端异常,不⼀定对,只是有个⼤概印象。如下:
下⾯就针对不同异常的捕获⼀⼀分析:
1.同步运⾏时错误
try {
let name = 'Jack';
console.log(nam);
} catch(e) {
console.log('捕获到异常:',e);
}
输出:
捕获到异常:ReferenceError: nam is not defined
at <anonymous>:3:15
2.不能捕获语法错误,我们修改⼀个代码,删掉⼀个单引号
try {
let name = 'Jack;
console.log(nam);
} catch(e) {
console.log('捕获到异常:',e);
}
输出:
Uncaught SyntaxError: Invalid or unexpected token
语法错误SyntaxError,不管是还是atch都没法捕获异常。但是不⽤担⼼,在你写好代码按下保存那⼀刻,编译器会帮你检查是否有语法错误,如果有错误有会有个很明显的红红的波浪线,把⿏标移上去就能看到报错信息。因此,⾯对SyntaxError语法错误,⼀定要⼩⼼⼩⼼再⼩⼼
3.异步错误
try {
setTimeout(() => {
undefined.map(v => v);
}, 1000)
} catch(e) {
console.log('捕获到异常:',e);
}
输出:
Uncaught TypeError: Cannot read property 'map' of undefined
at setTimeout (<anonymous>:3:11)
可以看到,并没有捕获到异常。
window. 不是万能的
当JS运⾏时错误发⽣时,window 会触发⼀个 ErrorEvent 接⼝的 error 事件,并执⾏ window.() 。/**
* @param {String} message 错误信息
* @param {String} source 出错⽂件
* @param {Number} lineno ⾏号
* @param {Number} colno 列号
* @param {Object} error Error对象(对象)
*/
window. = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
1.同步运⾏时错误
window. = function(message, source, lineno, colno, error) {
// message:错误信息(字符串)。
// source:发⽣错误的脚本URL(字符串)
// source:发⽣错误的脚本URL(字符串)
// lineno:发⽣错误的⾏号(数字)
// colno:发⽣错误的列号(数字)
// error:Error对象(对象)
console.log('捕获到异常:',{message, source, lineno, colno, error}); }
UndefVar;
可以看到,我们捕获了异常:
2.语法错误
window. = function(message, source, lineno, colno, error) { console.log('捕获到异常:',{message, source, lineno, colno, error}); }
let name = 'Jack; // 少个单引号
控制台打印出了这样的异常:
Uncaught SyntaxError: Invalid or unexpected token
可以看出,并没有捕获到异常。
3.异步运⾏时错误
window. = function(message, source, lineno, colno, error) { console.log('捕获到异常:',{message, source, lineno, colno, error}); }
setTimeout(() => {
UndefVar;
});
同样看到,我们捕获了异常:
4.⽹络请求的异常当前页面脚本发生错误
<script>
window. = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
return true;
}
</script>
<img src="./xxx.png">
我们发现,不论是静态资源异常,或者接⼝异常,错误都⽆法捕获到。
注意:
1.window. 函数只有在返回 true 的时候,异常才不会向上抛出(浏览器接收后报红),否则即使是知道异常的发⽣控
制台还是会显⽰ Uncaught Error: xxxxx
2.window. 最好写在所有JS脚本的前⾯,否则有可能捕获不到错误
3.window.⽆法捕获语法错误
那么问题来了,如何捕获静态资源加载错误呢?
window.addEventListener
当⼀项资源(如图⽚和脚本加载失败),加载资源的元素会触发⼀个Event接⼝的error事件,并执⾏该元素上的处理函数。这些error事件不会向上冒泡到window,不过(⾄少在 Chrome 中)能被单⼀的window.addEventListener 捕获。
<script>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
发布评论