Node.js API详解之 Error模块用法实例分析
本文实例讲述了Node.jsAPI详解之Error模块用法。分享给大家供大家参考,具体如下:
Node.jsAPI详解之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错误都会被作为异常处理,异常会立即产生并使用标准的JavaScriptthrow机制抛出一个错误。
这些都是使用JavaScript语言提供的try/catch语句处理的。
JavaScript的throw机制的任何使用都会引起异常,异常必须使用try/catch处理,
否则Node.js进程会立即退出。
除了少数例外,同步的API(任何不接受callback函数的阻塞方法,例如fs.readFileSync)会使用throw报告错误。
大多数的异步方法都接受一个callback函数,该函数会接受一个Error对象传入作为第一个参数。
如果第一个参数不是null而是一个Error实例,则说明发生了错误,应该进行处理。例:
constfs=require('fs'); fs.readFile('一个不存在的文件',(err,data)=>{ if(err){ console.error('读取文件出错!',err); return; } //否则处理数据 });
当一个异步方法被一个EventEmitter对象调用时,错误会被分发到对象的‘error'事件上。例:
constnet=require('net'); constconnection=net.connect('localhost'); //添加一个'error'事件句柄到一个流: connection.on('error',(err)=>{ //如果连接被服务器重置,或无法连接,或发生任何错误,则错误会被发送到这里。 console.error(err); }); connection.pipe(process.stdout);
Node.jsAPI中有一小部分普通的异步方法仍可能使用throw机制抛出异常,且必须使用try/catch处理。
这些方法并没有一个完整的列表;请参阅各个方法的文档以确定所需的合适的错误处理机制。
对于所有的EventEmitter对象,如果没有提供一个‘error'事件句柄,则错误会被抛出,
并造成Node.js进程报告一个未处理的异常且随即崩溃,除非:适当地使用domain模块或已经注册了一个process.on(‘uncaughtException')事件的句柄。
constEventEmitter=require('events'); constee=newEventEmitter(); setImmediate(()=>{ //这会使进程崩溃,因为还为添加'error'事件句柄。 ee.emit('error',newError('这会崩溃')); });
这种方式产生的错误无法使用try/catch截获,因为它们是在调用的代码已经退出后抛出的。
开发者必须查阅各个方法的文档以明确在错误发生时这些方法是如何冒泡的。
Error类
说明:
一个通用的JavaScriptError对象,它不表示错误发生的具体情况。
Error对象会捕捉一个“堆栈跟踪”,详细说明被实例化的Error对象在代码中的位置,并可能提供错误的文字描述。
只对于加密,如果在抛出错误时可以使用Error对象,则会将OpenSSL错误堆栈放入到名为opensslErrorStack的单独属性中。
所有由Node.js产生的错误,包括所有系统的和JavaScript的错误都实例化自或继承自Error类。
newError(message)
说明:
新建一个Error实例,并设置error.message属性以提供文本信息。
如果message传的是一个对象,则会调用message.toString()生成文本信息。
error.stack属性表示被调用的newError()在代码中的位置。
堆栈跟踪是基于V8的堆栈跟踪API的。
堆栈跟踪只会取(a)异步代码执行的开头或(b)Error.stackTraceLimit属性给出的栈帧中的最小项。
demo:
thrownewError('异常信息'); //Error:异常信息 //atObject.(/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:1:69) //atModule._compile(module.js:660:30) //atObject.Module._extensions..js(module.js:671:10) //atModule.load(module.js:573:32) //attryModuleLoad(module.js:513:12) //atFunction.Module._load(module.js:505:3) //atFunction.Module.runMain(module.js:701:10) //atstartup(bootstrap_node.js:193:16) //atbootstrap_node.js:617:3
Error.stackTraceLimit
说明:
Error.stackTraceLimit属性指定了堆栈跟踪收集的栈帧数量
(无论是newError().stack或Error.captureStackTrace(obj)产生的)。
默认值为10,但可设为任何有效的JavaScript数值。值改变后的变化会影响所有捕获到的堆栈跟踪。
如果设为一个非数值或负数,则堆栈跟踪不会捕捉任何栈帧。
demo:
Error.stackTraceLimit=5; try{ consta=1+b; }catch(err){ console.log(err.stack); } //ReferenceError:bisnotdefined //atObject.(/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:3:16) //atModule._compile(module.js:660:30) //atObject.Module._extensions..js(module.js:671:10) //atModule.load(module.js:573:32) //attryModuleLoad(module.js:513:12)
Error.captureStackTrace(targetObject[,constructorOpt])
说明:
在targetObject上创建一个.stack属性
当访问时返回一个表示代码中调用Error.captureStackTrace()的位置的字符串。
可选的constructorOpt参数接受一个函数。如果提供了,则constructorOpt之上包括自身在内的全部栈帧都会被生成的堆栈跟踪省略。
demo:
constmyObject={}; Error.captureStackTrace(myObject); console.log(myObject.stack); //Error //atObject.(/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:7) //atModule._compile(module.js:660:30) //atObject.Module._extensions..js(module.js:671:10) //atModule.load(module.js:573:32) //attryModuleLoad(module.js:513:12) //atFunction.Module._load(module.js:505:3) //atFunction.Module.runMain(module.js:701:10) //atstartup(bootstrap_node.js:193:16) //atbootstrap_node.js:617:3
error.code
说明:
error.code属性是标识错误类别的字符标签。
详见Node.jsErrorCodes
demo: try{ consta=1+b; }catch(err){ console.log(err.code); } //undefined
error.message
说明:
error.message属性是错误的字符串描述,通过调用newError(message)设置。
传给构造函数的message也会出现在Error的堆栈跟踪的第一行。
但是,Error对象创建后改变这个属性可能不会改变堆栈跟踪的第一行(比如当error.stack在该属性被改变之前被读取)。
demo:
try{ consta=1+b; }catch(err){ console.log(err.message); } //bisnotdefined
error.stack
说明:
error.stack属性是一个字符串,描述代码中Error被实例化的位置。
第一行会被格式化为:,
且带上一系列栈帧(每一行都以“at”开头)。每一帧描述了一个代码中导致错误生成的调用点。
V8引擎会试图显示每个函数的名称(变量名、函数名、或对象的方法名),但偶尔也可能找不到一个合适的名称。
如果V8引擎没法确定一个函数的名称,则只显示帧的位置信息。否则,在位置信息的旁边会显示明确的函数名。
注意,帧只由JavaScript函数产生。
demo:
try{ consta=1+b; }catch(err){ console.log(err.stack); } //ReferenceError:bisnotdefined //atObject.(/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:16) //atModule._compile(module.js:660:30) //atObject.Module._extensions..js(module.js:671:10) //atModule.load(module.js:573:32) //attryModuleLoad(module.js:513:12) //atFunction.Module._load(module.js:505:3) //atFunction.Module.runMain(module.js:701:10) //atstartup(bootstrap_node.js:193:16) //atbootstrap_node.js:617:3
AssertionError类
说明:
Error的子类,表示断言失败。这种错误通常表示实际值和预期值不相等。
demo:
constassert=require('assert'); assert.strictEqual(1,2); //AssertionError[ERR_ASSERTION]:1===2
RangeError类
说明:
Error的一个子类,表明一个函数的一个给定的参数的值不在可接受的集合或范围内;
无论是一个数字范围还是给定函数参数的选项的集合。
demo:
require('net').connect(-1); //RangeError[ERR_SOCKET_BAD_PORT]:Portshouldbe>0and<65536.Received-1.
ReferenceError类
说明:
Error的一个子类,表明试图访问一个未定义的变量。这些错误通常表明代码有拼写错误或程序已损坏。
虽然客户端代码可能产生和传播这些错误,但在实践中,只有V8引擎会这么做。
demo:
console.log(a); //ReferenceError:aisnotdefined
SyntaxError类
说明:
Error的一个子类,表明程序不是有效的JavaScript代码。这些错误是代码执行的结果产生和传播的。
代码执行可能产生自eval、Function、require或vm。这些错误几乎都表明程序已损坏。
demo:
eval('**'); //SyntaxError:Unexpectedtoken**
TypeError类
说明:
Error的一个子类,表明提供的参数不是一个被允许的类型。
例如,将一个函数传给一个期望字符串的参数会被视为一个TypeError。
demo:
require('url').parse(()=>{}); //TypeError[ERR_INVALID_ARG_TYPE]:The"url"argumentmustbeoftypestring.Receivedtypefunction
SystemError类
说明:
系统错误是当程序运行环境中发生异常时产生的。
有单独的异常类,并且有单独的属性:
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系统上,可通过运行man2intro、man3errno、或在线文档获取错误代码的详细清单和含义。
系统错误是由扩展的Error对象加上附加属性表现的。
常见的系统错误:
以下列表是不完整的,但列举了编写Node.js程序时会遇到的一些常见的系统错误。详细的列表可从ERRNO文档找到。
EACCES(拒绝访问):试图以被一个文件的访问权限禁止的方式访问一个文件。EADDRINUSE(地址已被使用):试图绑定一个服务器(net、http或https)到本地地址,但因另一个本地系统的服务器已占用了该地址而导致失败。
ECONNREFUSED(连接被拒绝):无法连接,因为目标机器积极拒绝。这通常是因为试图连接到外部主机上的废弃的服务。
ECONNRESET(连接被重置):一个连接被强行关闭。这通常是因为连接到远程socket超时或重启。常发生于http和net模块。
EEXIST(文件已存在):一个操作的目标文件已存在,而要求目标不存在。
EISDIR(是一个目录):一个操作要求一个文件,但给定的路径是一个目录。
EMFILE(系统打开了太多文件):已达到系统文件描述符允许的最大数量,且描述符的请求不能被满足直到至少关闭其中一个。当一次并行打开多个文件时会发生这个错误,尤其是在进程的文件描述限制数量较低的操作系统(如macOS)。要解决这个限制,可在运行Node.js进程的同一shell中运行ulimit-n2048。
ENOENT(无此文件或目录):通常是由fs操作引起的,表明指定的路径不存在,即给定的路径找不到文件或目录。
ENOTDIR(不是一个目录):给定的路径虽然存在,但不是一个目录。通常是由fs.readdir引起的。
ENOTEMPTY(目录非空):一个操作的目标是一个非空的目录,而要求的是一个空目录。通常是由fs.unlink引起的。
EPERM(操作不被允许):试图执行一个需要更高权限的操作。
EPIPE(管道损坏):写入一个管道、socket或FIFO时没有进程读取数据。常见于net和http层,表明远端要写入的流已被关闭。
ETIMEDOUT(操作超时):一个连接或发送的请求失败,因为连接方在一段时间后没有做出合适的响应。常见于http或net。往往标志着socket.end()没有被正确地调用
希望本文所述对大家node.js程序设计有所帮助。