未加星标

前端开发中的Error以及异常捕获

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2019 | 作者 红领巾 ] 0人收藏点击收藏

在前端项目中,由于javascript本身是一个弱类型语言,加上浏览器环境的复杂性,网络问题等等,很容易发生错误。做好网页错误监控,不断优化代码,提高代码健壮性是一项很重要的工作。本文将从Error开始,讲到如何捕获页面中的异常。文章较长,细节较多,请耐心观看。

前端开发中的Error JavaScript中的Error

JavaScript中, Error 是一个构造函数,通过它创建一个错误对象。当运行时错误产生时,Error的实例对象会被抛出。构造一个Error的语法如下:

// message: 错误描述 // fileName: 可选。被创建的Error对象的fileName属性值。默认是调用Error构造器代码所在的文件的名字。 // lineNumber: 可选。被创建的Error对象的lineNumber属性值。默认是调用Error构造器代码所在的文件的行号。 new Error([message[, fileName[, lineNumber]]]) 复制代码 ECMAScript标准:

Error有两个 标准 属性:

Error.prototype.name Error.prototype.message

例如,在chrome控制台中输入以下代码:

var a = new Error('错误测试'); console.log(a); // Error: 错误测试 // at <anonymous>:1:9 console.log(a.name); // Error console.log(a.message); // 错误测试 复制代码

Error只有一个 标准 方法:

Error.prototype.toString :返回表示一个表示错误的字符串。

接上面的代码:

a.toString(); // "Error: 错误测试" 复制代码 非标准的属性

各个浏览器厂商对于Error都有自己的实现。比如下面这些属性:

Error.prototype.fileName Error.prototype.lineNumber Error.prototype.columnNumber Error.prototype.stack

这些属性均不是标准属性,在生产环境中 谨慎使用 。不过现代浏览器差不多都支持了。

Error的种类

除了通用的Error构造函数外,JavaScript还有7个其他类型的错误构造函数。

InternalError: 创建一个代表Javascript引擎内部错误的异常抛出的实例。 如:"递归太多"。非ECMAScript标准。 RangeError: 数值变量或参数超出其有效范围。例子:var a = new Array(-1); EvalError: 与eval()相关的错误。eval()本身没有正确执行。 ReferenceError: 引用错误。 例子:console.log(b); SyntaxError: 语法错误。例子:var a = ; TypeError: 变量或参数不属于有效范围。例子:[1,2].split('.') URIError: 给encodeURI或decodeURl()传递的参数无效。例子:decodeURI('%2')

当JavaScript运行过程中出错时,会抛出上8种(上述7种加上通用错误类型)错误中的其中一种错误。错误类型可以通过 error.name 拿到。

你也可以基于Error构造自己的错误类型,这里就不展开了。

其他错误

上面介绍的都是JavaScript本身运行时会发生的错误。页面中还会有其他的异常,比如错误地操作了DOM。

DOMException

DOMException是W3C DOM核心对象,表示调用一个Web Api时发生的异常。什么是Web Api呢?最常见的就是DOM元素的一系列方法,其他还有XMLHttpRequest、Fetch等等等等,这里就不一一说明了。直接看下面一个操作DOM的例子:

var node = document.querySelector('#app'); var refnode = node.nextSibling; var newnode = document.createElement('div'); node.insertBefore(newnode, refnode); // 报错:Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node. 复制代码

单从JS代码逻辑层面来看,没有问题。但是代码的操作不符合DOM的规则。

DOMException 构造函数的语法如下:

// message: 可选,错误描述。 // name: 可选,错误名称。常量,具体值可以在这里找到:https://developer.mozilla.org/zh-CN/docs/Web/API/DOMException new DOMException([message[, name]]); 复制代码

DOMException 有以下三个属性:

DOMException.code DOMException.message DOMException.name

以上面那段错误代码为例,其抛出的DOMException各属性的值为:

code: 8 message: "Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node." name: "NotFoundError" 复制代码 Promise 产生的异常

在 Promise 中,如果 Promise 被 reject 了,就会抛出异常: PromiseRejectionEvent 。注意,下面两种情况都会导致 Promise 被 reject :

Promise.reject Promise

PromiseRejectionEvent 的构造函数目前在浏览器中大多都不兼容,这里就不说了。

PromiseRejectionEvent 的属性有两个:

PromiseRejectionEvent.promise :被 reject 的 Promise 。 PromiseRejectionEvent.reason : Promise 被 reject 的原因。会传递给 reject 。 Promsie 的 catch 中的参数。 加载资源出错

由于网络,安全等原因,网页加载资源失败,请求接口出错等,也是一种常见的错误。

关于错误的小结

一个网页在运行过程中,可能发生四种错误:

JavaScript在运行过程,语言自身抛出的异常。 JavaScript在运行过程中,调用Web Api时发生异常。 Promise中的拒绝。 网页加载资源,调用接口时发生异常。

我认为,对于前两种错误,我们在平时的开发过程中,不用特别去区分,可以统一成:【代码出错】。

捕获错误

网页发生错误,开发者如何捕获这些错误呢 ? 常见的有以下方法。

try...catch...

try...catch… 大家都不陌生了。一般用来在具体的代码逻辑中捕获错误。

try { throw new Error("oops"); } catch (ex) { console.log("error", ex.message); // error oops } 复制代码

当 try-block 中的代码发生异常时,可以在 catck-block 中将异常接住,浏览器便不会抛出错误。但是,这种方式并不能捕获异步代码中的错误,如:

try { setTimeout(function(){ throw new Error('lala'); },0); } catch(e) { console.log('error', e.message); } 复制代码

这个时候,浏览器依然会抛出错误: Uncaught Error: lala 。

试想以下,如果我们将所有的代码合理的划分,然后都用 try catch 包起来,是不是就可以捕获到所有的错误了呢?可以通过编译工具来实现这个功能。不过, try catch 是比较耗费性能的。

window.onerror window.onerror = function(message, source, lineno, colno, error) { ... } 复制代码

函数参数:

message source lineno colno error

注意,如果这个函数返回 true ,那么将会阻止执行浏览器默认的错误处理函数。

window.addEventListener('error') window.addEventListener('error', function(event) { ... }) 复制代码 我们调用 Object.prototype.toString.call(event) ,返回的是 [object ErrorEvent] 。可以看到 event 是 ErrorEvent 对象的实例。 ErrorEvent 是事件对象在脚本发生错误时产生,从 Event 继承而来。由于是事件,自然可以拿到 target 属性。 ErrorEvent 还包括了错误发生时的信息。 ErrorEvent.prototype.message: 字符串,包含了所发生错误的描述信息。 ErrorEvent.prototype.filename: 字符串,包含了发生错误的脚本文件的文件名。 ErrorEvent.prototype.lineno: 数字,包含了错误发生时所在的行号。 ErrorEvent.prototype.colno: 数字,包含了错误发生时所在的列号。 ErrorEvent.prototype.error: 发生错误时所抛出的 Error 对象。

注意,这里的 ErrorEvent.prototype.error 对应的Error对象,就是上文提到的 Error , InternalError , RangeError , EvalError , ReferenceError , SyntaxError , TypeError , URIError , DOMException 中的一种。

window.addEventListener('unhandledrejection') window.addEventListener('unhandledrejection', function (event) { ... }); 复制代码

在使用 Promise 的时候,如果没有声明 catch 代码块, Promise 的异常会被抛出。 只能 通过这个方法或者 window.onunhandledrejection 才能捕获到该异常。

event 就是上文提到的 PromiseRejectionEvent 。我们只需要关注其 reason 就行。

window.onerror 和 window.addEventListener('error')的区别 首先是 事件监听器 和 事件处理器 的区别。监听器只能声明一次,后续的声明会覆盖之前的声明。而事件处理器则可以绑定多个回调函数。 资源( img 或 script )加载失败时,加载资源的元素会触发一个 Event 接口的 error 事件,并执行该元素上的 onerror() 处理函数。但这些error事件不会向上冒泡到window。不过,这些 error 事件能被 window.addEventListener('error') 捕获。也就是说,**面对资源加载失败的错误,只能用 window.addEventListerner('error') , window.onerror **无效。 关于错误捕获的小结 我认为,在开发的过程中,对于容易出错的地方,可以使用 try{}catch(){} 来进行错误的捕获,做好兜底处理,避免页面挂掉。而对于全局的错误捕获,在现代浏览器中,我倾向于只使用使用 window.addEventListener('error') , window.addEventListener('unhandledrejection') 就行了。如果需要考虑兼容性,需要加上 window.onerror ,三者同时使用, window.addEv

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:前端开发中的Error以及异常捕获
本站链接:https://www.codesec.net/view/628065.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(23)