如何优雅处理前端异常?
前端一直是距离用户最近的一层,随着产品的日益完善,我们会更加注重用户体验,而前端异常却如鲠在喉,甚是烦人。
一、为什么要处理异常?异常是不可控的,会影响最终的呈现结果,但是我们有充分的理由去做这样的事情。
增强用户体验;远程定位问题;未雨绸缪,及早发现问题;无法复线问题,尤其是移动端,机型,系统都是问题;完善的前端方案,前端监控系统;对于 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 <anonymous>:3:15
2. 不能捕获到语法错误,我们修改一下代码,删掉一个单引号:
try { let name = 'jartto; console.log(nam);} catch(e) { console.log('捕获到异常:',e);}
输出:
Uncaught SyntaxError: Invalid or unexpected token
不过语法错误在我们开发阶段就可以看到,应该不会顺利上到线上环境。
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.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;
可以看到,我们捕获到了异常:
2. 再试试语法错误呢?
window.onerror = function(message, source, lineno, colno, error) {console.log('捕获到异常:',{message, source, lineno, colno, error});}let name = 'Jartto
控制台打印出了这样的异常:
Uncaught SyntaxError: Invalid or unexpected token
什么,竟然没有捕获到语法错误?
3. 怀着忐忑的心,我们最后来试试异步运行时错误:
window.onerror = function(message, source, lineno, colno, error) { console.log('捕获到异常:',{message, source, lineno, colno, error});}setTimeout(() => { Jartto;});
控制台输出了:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。