Node.js API详解之 Error模块用法实例分析


Posted in Javascript onMay 14, 2020

本文实例讲述了Node.js API详解之 Error模块用法。分享给大家供大家参考,具体如下:

Node.js API详解之 Error

Node.js 中运行的应用程序一般会遇到以下四类错误:
1.标准的 JavaScript 错误:
EvalError : 当调用 eval() 失败时抛出。
SyntaxError : 当 JavaScript 语法错误时抛出。
RangeError : 当值不在预期范围内时抛出。
ReferenceError : 当使用未定义的变量时抛出。
TypeError : 当传入错误类型的参数时抛出。
URIError : 当全局的 URI 处理函数被误用时抛出。
2.由底层操作系触发的系统错误,例如试图打开一个不存在的文件、试图通过一个已关闭的 socket 发送数据等。
3.由应用程序代码触发的用户自定义的错误。
4.断言错误是错误的一个特殊类别,每当 Node.js 检测到一个不应该发生的异常逻辑时触发。 这类错误通常由 assert 模块引起。
所有由 Node.js 引起的 JavaScript 错误与系统错误都继承自或实例化自标准的 JavaScript 类,且保证至少提供类中的属性。

错误的冒泡和捕获

说明:

Node.js 支持几种当应用程序运行时发生的错误的冒泡和处理的机制。
如何报告和处理这些错误完全取决于错误的类型和被调用的 API 的风格。
所有 JavaScript 错误都会被作为异常处理,异常会立即产生并使用标准的 JavaScript throw 机制抛出一个错误。
这些都是使用 JavaScript 语言提供的 try / catch 语句处理的。
JavaScript 的 throw 机制的任何使用都会引起异常,异常必须使用 try / catch 处理,
否则 Node.js 进程会立即退出。

除了少数例外,同步的 API(任何不接受 callback 函数的阻塞方法,例如 fs.readFileSync)会使用 throw 报告错误。
大多数的异步方法都接受一个 callback 函数,该函数会接受一个 Error 对象传入作为第一个参数。
如果第一个参数不是 null 而是一个 Error 实例,则说明发生了错误,应该进行处理。例:

const fs = require('fs');
 fs.readFile('一个不存在的文件', (err, data) => {
 if (err) {
 console.error('读取文件出错!', err);
 return;
 }
 // 否则处理数据
 });

当一个异步方法被一个 EventEmitter 对象调用时,错误会被分发到对象的 ‘error' 事件上。例:

const net = require('net');
 const connection = net.connect('localhost');
 // 添加一个 'error' 事件句柄到一个流:
 connection.on('error', (err) => {
 // 如果连接被服务器重置,或无法连接,或发生任何错误,则错误会被发送到这里。 
 console.error(err);
 });
 connection.pipe(process.stdout);

Node.js API 中有一小部分普通的异步方法仍可能使用 throw 机制抛出异常,且必须使用 try / catch 处理。
这些方法并没有一个完整的列表;请参阅各个方法的文档以确定所需的合适的错误处理机制。
对于所有的 EventEmitter 对象,如果没有提供一个 ‘error' 事件句柄,则错误会被抛出,
并造成 Node.js 进程报告一个未处理的异常且随即崩溃,除非: 适当地使用 domain 模块或已经注册了一个 process.on(‘uncaughtException') 事件的句柄。

const EventEmitter = require('events');
 const ee = new EventEmitter();
 setImmediate(() => {
 // 这会使进程崩溃,因为还为添加 'error' 事件句柄。
 ee.emit('error', new Error('这会崩溃'));
 });

这种方式产生的错误无法使用 try / catch 截获,因为它们是在调用的代码已经退出后抛出的。
开发者必须查阅各个方法的文档以明确在错误发生时这些方法是如何冒泡的。

Error 类

说明:

一个通用的 JavaScript Error 对象,它不表示错误发生的具体情况。
Error 对象会捕捉一个“堆栈跟踪”,详细说明被实例化的 Error 对象在代码中的位置,并可能提供错误的文字描述。
只对于加密,如果在抛出错误时可以使用 Error 对象,则会将OpenSSL错误堆栈放入到名为 opensslErrorStack 的单独属性中。
所有由 Node.js 产生的错误,包括所有系统的和 JavaScript 的错误都实例化自或继承自 Error 类。

new Error(message)

说明:

新建一个 Error 实例,并设置 error.message 属性以提供文本信息。
如果 message 传的是一个对象,则会调用 message.toString() 生成文本信息。
error.stack 属性表示被调用的 new Error() 在代码中的位置。
堆栈跟踪是基于 V8 的堆栈跟踪 API 的。
堆栈跟踪只会取(a)异步代码执行的开头或(b)Error.stackTraceLimit 属性给出的栈帧中的最小项。

demo:

throw new Error('异常信息');
// Error: 异常信息
//  at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:1:69)
//  at Module._compile (module.js:660:30)
//  at Object.Module._extensions..js (module.js:671:10)
//  at Module.load (module.js:573:32)
//  at tryModuleLoad (module.js:513:12)
//  at Function.Module._load (module.js:505:3)
//  at Function.Module.runMain (module.js:701:10)
//  at startup (bootstrap_node.js:193:16)
//  at bootstrap_node.js:617:3

Error.stackTraceLimit

说明:

Error.stackTraceLimit 属性指定了堆栈跟踪收集的栈帧数量
(无论是 new Error().stack 或 Error.captureStackTrace(obj) 产生的)。
默认值为 10 ,但可设为任何有效的 JavaScript 数值。 值改变后的变化会影响所有捕获到的堆栈跟踪。
如果设为一个非数值或负数,则堆栈跟踪不会捕捉任何栈帧。

demo:

Error.stackTraceLimit = 5; 
try{
 const a = 1 + b;
}catch(err){
 console.log(err.stack);
}
// ReferenceError: b is not defined
//  at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:3:16)
//  at Module._compile (module.js:660:30)
//  at Object.Module._extensions..js (module.js:671:10)
//  at Module.load (module.js:573:32)
//  at tryModuleLoad (module.js:513:12)

Error.captureStackTrace(targetObject[, constructorOpt])

说明:

在 targetObject 上创建一个 .stack 属性
当访问时返回一个表示代码中调用 Error.captureStackTrace() 的位置的字符串。
可选的 constructorOpt 参数接受一个函数。 如果提供了,则 constructorOpt 之上包括自身在内的全部栈帧都会被生成的堆栈跟踪省略。

demo:

const myObject = {};
Error.captureStackTrace(myObject);
console.log( myObject.stack ); 
// Error
//  at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:7)
//  at Module._compile (module.js:660:30)
//  at Object.Module._extensions..js (module.js:671:10)
//  at Module.load (module.js:573:32)
//  at tryModuleLoad (module.js:513:12)
//  at Function.Module._load (module.js:505:3)
//  at Function.Module.runMain (module.js:701:10)
//  at startup (bootstrap_node.js:193:16)
//  at bootstrap_node.js:617:3

error.code

说明:

error.code 属性是标识错误类别的字符标签。

详见 Node.js Error Codes

demo:
try{
 const a = 1 + b;
}catch(err){
 console.log(err.code);
}
// undefined

error.message

说明:

error.message 属性是错误的字符串描述,通过调用 new Error(message) 设置。
传给构造函数的 message 也会出现在 Error 的堆栈跟踪的第一行。
但是,Error 对象创建后改变这个属性可能不会改变堆栈跟踪的第一行(比如当 error.stack 在该属性被改变之前被读取)。

demo:

try{
 const a = 1 + b;
}catch(err){
 console.log(err.message);
}
// b is not defined

error.stack

说明:

error.stack 属性是一个字符串,描述代码中 Error 被实例化的位置。

第一行会被格式化为 : ,
且带上一系列栈帧(每一行都以 “at ” 开头)。 每一帧描述了一个代码中导致错误生成的调用点。
V8 引擎会试图显示每个函数的名称(变量名、函数名、或对象的方法名),但偶尔也可能找不到一个合适的名称。
如果 V8 引擎没法确定一个函数的名称,则只显示帧的位置信息。 否则,在位置信息的旁边会显示明确的函数名。
注意,帧只由 JavaScript 函数产生。

demo:

try{
 const a = 1 + b;
}catch(err){
 console.log(err.stack);
}
// ReferenceError: b is not defined
//  at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:16)
//  at Module._compile (module.js:660:30)
//  at Object.Module._extensions..js (module.js:671:10)
//  at Module.load (module.js:573:32)
//  at tryModuleLoad (module.js:513:12)
//  at Function.Module._load (module.js:505:3)
//  at Function.Module.runMain (module.js:701:10)
//  at startup (bootstrap_node.js:193:16)
//  at bootstrap_node.js:617:3

AssertionError 类

说明:

Error 的子类,表示断言失败。 这种错误通常表示实际值和预期值不相等。

demo:

const assert = require('assert');
assert.strictEqual(1, 2);
// AssertionError [ERR_ASSERTION]: 1 === 2

RangeError 类

说明:

Error 的一个子类,表明一个函数的一个给定的参数的值不在可接受的集合或范围内;
无论是一个数字范围还是给定函数参数的选项的集合。

demo:

require('net').connect(-1);
// RangeError [ERR_SOCKET_BAD_PORT]: Port should be > 0 and < 65536. Received -1.

ReferenceError 类

说明:

Error 的一个子类,表明试图访问一个未定义的变量。 这些错误通常表明代码有拼写错误或程序已损坏。
虽然客户端代码可能产生和传播这些错误,但在实践中,只有 V8 引擎会这么做。

demo:

console.log( a );
// ReferenceError: a is not defined

SyntaxError 类

说明:

Error 的一个子类,表明程序不是有效的 JavaScript 代码。 这些错误是代码执行的结果产生和传播的。
代码执行可能产生自 eval、Function、require 或 vm。 这些错误几乎都表明程序已损坏。

demo:

eval('**');
// SyntaxError: Unexpected token **

TypeError 类

说明:

Error 的一个子类,表明提供的参数不是一个被允许的类型。
例如,将一个函数传给一个期望字符串的参数会被视为一个 TypeError。

demo:

require('url').parse(() => { });
// TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received type function

System Error 类

说明:

系统错误是当程序运行环境中发生异常时产生的。
有单独的异常类,并且有单独的属性:
error.code属性是一个表示错误码的字符串,总是 E 带上一串大写字母。
error.errno属性是一个数值或字符串。 如果返回一个数值,则数值是一个负数,
对应 libuv 错误处理 中定义的错误码。 如果返回一个字符串,则同 error.code。
error.syscall属性是一个字符串,描述失败的 系统调用。
error.path属性是一个字符串,包含了相关不可用路径名。
error.address属性是对链接失败的地址的描述。
error.port是一个链接端口不可用的端口值

异常与错误

说明:

JavaScript 异常是一个作为一个无效操作的结果或作为一个 throw 声明的目标所抛出的值。
虽然它不要求这些值是 Error 的实例或继承自 Error 的类的实例,
但所有通过 Node.js 或 JavaScript 运行时抛出的异常都是 Error 实例。
有些异常在 JavaScript 层是无法恢复的。 这些异常总会引起 Node.js 进程的崩溃。
例如 assert() 检测或在 C++ 层调用的 abort()。

系统错误

说明:

系统错误是当程序运行环境中发生异常时产生的。
特别是,当应用程序违反了操作系统的限制时发生的操作错误,例如试图读取一个不存在的文件或用户没有足够的权限。
系统错误通常产生于系统调用层级。
在大多数 Unix 系统上,可通过运行 man 2 intro、man 3 errno、或在线文档获取错误代码的详细清单和含义。
系统错误是由扩展的 Error 对象加上附加属性表现的。

常见的系统错误:

以下列表是不完整的,但列举了编写 Node.js 程序时会遇到的一些常见的系统错误。 详细的列表可从 ERRNO 文档找到。
EACCES (拒绝访问): 试图以被一个文件的访问权限禁止的方式访问一个文件。

EADDRINUSE (地址已被使用): 试图绑定一个服务器(net、http 或 https)到本地地址,但因另一个本地系统的服务器已占用了该地址而导致失败。

ECONNREFUSED (连接被拒绝): 无法连接,因为目标机器积极拒绝。 这通常是因为试图连接到外部主机上的废弃的服务。

ECONNRESET (连接被重置): 一个连接被强行关闭。 这通常是因为连接到远程 socket 超时或重启。 常发生于 http 和 net 模块。

EEXIST (文件已存在): 一个操作的目标文件已存在,而要求目标不存在。

EISDIR (是一个目录): 一个操作要求一个文件,但给定的路径是一个目录。

EMFILE (系统打开了太多文件): 已达到系统文件描述符允许的最大数量,且描述符的请求不能被满足直到至少关闭其中一个。 当一次并行打开多个文件时会发生这个错误,尤其是在进程的文件描述限制数量较低的操作系统(如 macOS)。 要解决这个限制,可在运行 Node.js 进程的同一 shell 中运行 ulimit -n 2048。

ENOENT (无此文件或目录): 通常是由 fs 操作引起的,表明指定的路径不存在,即给定的路径找不到文件或目录。

ENOTDIR (不是一个目录): 给定的路径虽然存在,但不是一个目录。 通常是由 fs.readdir 引起的。

ENOTEMPTY (目录非空): 一个操作的目标是一个非空的目录,而要求的是一个空目录。 通常是由 fs.unlink 引起的。

EPERM (操作不被允许): 试图执行一个需要更高权限的操作。

EPIPE (管道损坏): 写入一个管道、socket 或 FIFO 时没有进程读取数据。 常见于 net 和 http 层,表明远端要写入的流已被关闭。

ETIMEDOUT (操作超时): 一个连接或发送的请求失败,因为连接方在一段时间后没有做出合适的响应。 常见于 http 或 net。 往往标志着 socket.end() 没有被正确地调用

希望本文所述对大家node.js程序设计有所帮助。

Javascript 相关文章推荐
javascript getElementsByName()的用法说明
Jul 31 Javascript
jQuery之选择组件的深入解析
Jun 19 Javascript
escape函数解决js中ajax传递中文出现乱码问题
Oct 30 Javascript
JavaScript插件化开发教程(五)
Feb 01 Javascript
JavaScript中操作Mysql数据库实例
Apr 02 Javascript
Javascript中arguments和arguments.callee的区别浅析
Apr 24 Javascript
Bootstrap零基础学习第一课之模板
Jul 18 Javascript
浅谈javascript:两种注释,声明变量,定义函数
Oct 05 Javascript
清除js缓存的多种方法总结
Dec 09 Javascript
jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)
May 19 jQuery
node使用Koa2搭建web项目的方法
Oct 17 Javascript
layui清空,重置表单数据的实例
Sep 12 Javascript
微信小程序 获取手机号 JavaScript解密示例代码详解
May 14 #Javascript
JavaScript, select标签元素左右移动功能实现
May 14 #Javascript
vue实现商品列表的添加删除实例讲解
May 14 #Javascript
Vue 自适应高度表格的实现方法
May 13 #Javascript
ES6函数实现排它两种写法解析
May 13 #Javascript
详解vue-router的Import异步加载模块问题的解决方案
May 13 #Javascript
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
May 13 #Javascript
You might like
PHP 判断变量类型实现代码
2009/10/23 PHP
php与XML、XSLT、Mysql的结合运用实现代码
2009/11/19 PHP
php操作memcache缓存方法分享
2015/06/03 PHP
防止动态加载JavaScript引起的内存泄漏问题
2009/10/08 Javascript
基于node.js的快速开发透明代理
2010/12/25 Javascript
js原生appendChild的bug解决心得分享
2013/07/01 Javascript
js将控件隐藏的方法及display属性介绍
2013/07/04 Javascript
时间戳转换为时间 年月日时间的JS函数
2013/08/19 Javascript
jQuery+jsp下拉框联动获取本地数据的方法(附源码)
2015/12/03 Javascript
JavaScript提高性能知识点汇总
2016/01/15 Javascript
jQuery动态加载css文件实现方法
2016/06/15 Javascript
从0开始学Vue
2016/10/27 Javascript
vue2组件实现懒加载浅析
2017/03/29 Javascript
jQuery图片查看插件Magnify开发详解
2017/12/25 jQuery
vue2.0 实现导航守卫的具体用法(路由守卫)
2018/05/17 Javascript
jquery实现搜索框功能实例详解
2018/07/23 jQuery
vue 项目中使用Loading组件的示例代码
2018/08/31 Javascript
Centos7 安装Node.js10以上版本的方法步骤
2019/10/15 Javascript
Element InfiniteScroll无限滚动的具体使用方法
2020/07/27 Javascript
Javascript基于OOP实实现探测器功能代码实例
2020/08/26 Javascript
利用Python破解验证码实例详解
2016/12/08 Python
Python实现二分查找与bisect模块详解
2017/01/13 Python
python使用opencv驱动摄像头的方法
2018/08/03 Python
pytorch permute维度转换方法
2018/12/14 Python
python3 中的字符串(单引号、双引号、三引号)以及字符串与数字的运算
2019/07/18 Python
使用Python制作一个打字训练小工具
2019/10/01 Python
python3用PyPDF2解析pdf文件,用正则匹配数据方式
2020/05/12 Python
Keras 加载已经训练好的模型进行预测操作
2020/06/17 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
用HTML5的canvas实现一个炫酷时钟效果
2016/05/20 HTML / CSS
世界上最大的在线旅行社新加坡网站:Expedia新加坡
2016/08/25 全球购物
与UNIX有关的几个名词
2015/09/17 面试题
播音主持女孩的自我评价分享
2013/11/20 职场文书
安卓程序员求职信
2014/02/28 职场文书
职位说明书范文
2014/05/07 职场文书
优秀共产党员演讲稿
2014/09/04 职场文书