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

本文实例讲述了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程序设计有所帮助。

(0)

相关推荐

  • Node.js API详解之 querystring用法实例分析

    本文实例讲述了Node.js API详解之 querystring用法.分享给大家供大家参考,具体如下: Node.js API详解之 querystring querystring模块提供了一些实用函数,用于解析与格式换URL查询字符串 通过 const querystring = require('querystring'); 的方式引用querystrings模块 目录: querystring.escape(str) querystring.unescape(str) querystri

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

    本文实例讲述了Node.js API详解之 timer模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 timer timer 模块暴露了一个全局的 API,用于在某个未来时间段调用调度函数. 因为定时器函数是全局的,所以使用该 API 无需调用 require('timers'). Node.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API, 它使用了一个不同的内部实现,它是基于 Node.js 事件循环构建的. setImmediate(call

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

    本文实例讲述了Node.js API详解之 os模块用法.分享给大家供大家参考,具体如下: os是Node的一个基础模块,提供了一些操作系统相关的属性接口. 通过 const os = require('os'); 的方式引用os模块,我们接着看下os都有哪些功能 说明: 一个字符串常量,定义操作系统相关的行末标志:POSIX 系统上值为\n,Windows下的值为\r\n demo: console.log('abc'+ os.EOL +'123'); //abc //123 os.arch(

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

    本文实例讲述了Node.js API详解之 vm模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 vm vm 模块提供了一系列 API 用于在 V8 虚拟机环境中编译和运行代码. JavaScript 代码可以被编译并立即运行,或编译.保存然后再运行. 常见的用法是在沙盒中运行代码.沙盒代码使用不同的V8上下文. const vm = require('vm'); const x = 1; const sandbox = { x: 2 }; vm.createContex

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

    本文实例讲述了Node.js API详解之 assert模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 assert assert 模块提供了断言测试的函数,用于测试不变式. 断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真, 可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言. 同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言. 使用断言可以创建更稳定.品质更好且不易于出错的代码. 当需要在一个值为

  • Node.js API详解之 readline模块用法详解

    本文实例讲述了Node.js API详解之 readline模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 readline readline 模块提供了一个接口,用于从可读流(如 process.stdin)读取数据,每次读取一行. 它可以通过以下方式使用: const readline = require('readline'); readline 模块的基本用法: const readline = require('readline'); const rl = r

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

    本文实例讲述了Node.js API详解之 dgram模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 dgram dgram模块提供了 UDP 数据包 socket 的实现. 使用以下方式引用: const dgram = require('dgram'); dgram.createSocket(options[, callback]) 说明: 创建一个 dgram.Socket 对象. 一旦创建了套接字,调用 socket.bind() 会指示套接字开始监听数据报消息

  • Node.js API详解之 tty功能与用法实例分析

    本文实例讲述了Node.js API详解之 tty功能与用法.分享给大家供大家参考,具体如下: tty 可以理解为终端的意思.tty 模块提供终端相关的接口,用来获取终端的行数列数等. 通过 const tty = require('tty'); 的方式引用 tty 模块 process.stdout.isTTY 说明: 此属性位于 process 模块,用来判断 Node.js 是否运行在一个 TTY 环境中 demo: console.log(process.stdout.isTTY) //

  • Node.js API详解之 zlib模块用法分析

    本文实例讲述了Node.js API详解之 zlib模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 zlib zlib模块提供通过 Gzip 和 Deflate/Inflate 实现的压缩功能,可以通过这样使用它: const zlib = require('zlib'); 压缩或者解压数据流(例如一个文件)通过zlib流将源数据流传输到目标流中来完成: const gzip = zlib.createGzip(); const fs = require('fs');

  • Node.js API详解之 string_decoder用法实例分析

    本文实例讲述了Node.js API详解之 string_decoder用法.分享给大家供大家参考,具体如下: string_decoder 模块提供了一个 API,用于把 Buffer 对象解码成字符串. 对于参数末尾不完整的多字节字符,string_decoder会将其保存在内部的buffer中,当再次解码时,补充到参数开头. 通过 const { StringDecoder } = require('string_decoder'); 的方式引用string_decoder模块. 目录:

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

    本文实例讲述了Node.js API详解之 util模块用法.分享给大家供大家参考,具体如下: Node.js API详解之 util util 模块主要用于支持 Node.js 内部 API 的需求.提供了大部分实用工具. 通过 const util = require('util'); 的方式引用util模块 util.callbackify(original) 说明: original:传递一个 async 函数,或者是一个返回Promise的异步函数. callbackify会返回一个方

随机推荐