异常监控:教你如何优雅的处理前端异常

关注  高级前端进阶 ,回复“ 加群

加入我们一起学习,天天进步

作者:Jartto’s blog

来源:http://jartto.wang/2018/11/20/js-exception-handling/

前端一直是距离用户最近的一层,随着产品的日益完善,我们会更加注重用户体验,而前端异常却如鲠在喉,甚是烦人。

一、为什么要处理异常?

异常是不可控的,会影响最终的呈现结果,但是我们有充分的理由去做这样的事情。

  1. 增强用户体验;

  2. 远程定位问题;

  3. 未雨绸缪,及早发现问题;

  4. 无法复线问题,尤其是移动端,机型,系统都是问题;

  5. 完善的前端方案,前端监控系统;

对于 JS 而言,我们面对的仅仅只是异常,异常的出现不会直接导致 JS 引擎崩溃,最多只会使当前执行的任务终止。

二、需要处理哪些异常?

对于前端来说,我们可做的异常捕获还真不少。总结一下,大概如下:

  • JS 语法错误、代码异常

  • AJAX 请求异常

  • 静态资源加载异常

  • Promise 异常

  • Iframe 异常

  • 跨域 Script error

  • 崩溃和卡顿

下面我会针对每种具体情况来说明如何处理这些异常。

三、Try-Catch 的误区

try-catch 只能捕获到同步的运行时错误,对语法和异步错误却无能为力,捕获不到。

  1. 同步运行时错误:

try {

let name = ‘jartto’ ;

console .log(nam);

} catch (e) {

console .log( ‘捕获到异常:’ ,e);

}

输出:

捕获到异常: ReferenceError : nam is not defined

at :
3

:

15

  1. 不能捕获到具体的语法错误,只有一个语法错误提示。我们修改一下代码,删掉一个单引号:

try {

let name =

‘jartto;

console.log(nam);

} catch(e) {

console.log(‘

捕获到异常:

‘,e);

}

输出:

Uncaught SyntaxError : Invalid or unexpected token

不过语法错误在我们开发阶段就可以看到,应该不会顺利上到线上环境。

  1. 异步错误

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.onerror 不是万能的

当 JS 运行时错误发生时,window 会触发一个 ErrorEvent 接口的 error 事件,并执行 window.onerror()。

/**

* @param {String} message 错误信息

* @param {String} source 出错文件

* @param {Number} lineno 行号

* @param {Number} colno 列号

* @param {Object} error Error对象(对象)

window .onerror = function ( message, source, lineno, colno, error ) {

console .log( ‘捕获到异常:’ ,{message, source, lineno, colno, error});

}

  1. 首先试试同步运行时错误

window .onerror = function ( message, source, lineno, colno, error ) {

// message:错误信息(字符串)。

// source:发生错误的脚本URL(字符串)

// lineno:发生错误的行号(数字)

// colno:发生错误的列号(数字)

// error:Error对象(对象)

console .log( ‘捕获到异常:’ ,{message, source, lineno, colno, error});

}

Jartto;

可以看到,我们捕获到了异常:

  1. 再试试语法错误呢?

window .onerror = function ( message, source, lineno, colno, error ) {

console .log( ‘捕获到异常:’ ,{message, source, lineno, colno, error});

}

let

name =

‘Jartto

控制台打印出了这样的异常:

Uncaught SyntaxError : Invalid or unexpected token

什么,竟然没有捕获到语法错误?

  1. 怀着忐忑的心,我们最后来试试异步运行时错误:

window .onerror = function ( message, source, lineno, colno, error ) {

console .log( ‘捕获到异常:’ ,{message, source, lineno, colno, error});

}

setTimeout( () => {

Jartto;

});

控制台输出了:

捕获到异常:{ message : “Uncaught ReferenceError: Jartto is not defined” , source : “http://127.0.0.1:8001/” , lineno : 36 , colno : 5 , error : ReferenceError : Jartto is not defined

at setTimeout (http:

//127.0.0.1:8001/:36:5)}

  1. 接着,我们试试网络请求异常的情况: