开发手册 欢迎您!
软件开发者资料库

错误(Errors) | Node.js

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。Node.js 的包管理器 npm,是全球最大的开源库生态系统。

Node.js v8.x 中文文档


目录

Error (错误)#

Node.js 中运行的应用程序一般会遇到以下四类错误:

  • 标准的 JavaScript 错误:
    • : 当调用 eval() 失败时抛出。
    • : 当 JavaScript 语法错误时抛出。
    • : 当值不在预期范围内时抛出。
    • : 当使用未定义的变量时抛出。
    • : 当传入错误类型的参数时抛出。
    • : 当全局的 URI 处理函数被误用时抛出。
  • 由底层操作系触发的系统错误,例如试图打开一个不存在的文件、试图通过一个已关闭的 socket 发送数据等。
  • 由应用程序代码触发的用户自定义的错误。
  • 断言错误是错误的一个特殊类别,每当 Node.js 检测到一个不应该发生的异常逻辑时触发。这类错误通常由 assert 模块引起。

所有由 Node.js 引起的 JavaScript 错误与系统错误都继承自或实例化自标准的 JavaScript 类,且保证至少提供类中的属性。

错误的冒泡和捕获#

Node.js 支持几种当应用程序运行时发生的错误的冒泡和处理的机制。如何报告和处理这些错误完全取决于错误的类型和被调用的 API 的风格。

所有 JavaScript 错误都会被作为异常处理,异常会立即产生并使用标准的 JavaScript throw 机制抛出一个错误。这些都是使用 JavaScript 语言提供的 try / catch 语句处理的。

// 抛出一个 ReferenceError,因为 z 为 undefinedtry {  const m = 1;  const n = m + z;} catch (err) {  // 在这里处理错误。}

JavaScript 的 throw 机制的任何使用都会引起异常,异常必须使用 try / catch 处理,否则 Node.js 进程会立即退出。

除了少数例外,同步的 API(任何不接受 callback 函数的阻塞方法,例如 [fs.readFileSync])会使用 throw 报告错误。

异步的 API 中发生的错误可能会以多种方式进行报告:

  • 大多数的异步方法都接受一个 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 处理。这些方法并没有一个完整的列表;请参阅各个方法的文档以确定所需的合适的错误处理机制。

'error' 事件机制的使用常见于基于流基于事件触发器的 API,它们本身就代表了一系列的异步操作(相对于要么成功要么失败的单一操作)。

对于所有的 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-first callbacks#

Most asynchronous methods exposed by the Node.js core API follow an idiomaticpattern referred to as an error-first callback (sometimes referred to asa Node.js style callback). With this pattern, a callback function is passedto the method as an argument. When the operation either completes or an erroris raised, the callback function is called withthe Error object (if any) passed as the first argument. If no error wasraised, the first argument will be passed as null.

const fs = require('fs');function errorFirstCallback(err, data) {  if (err) {    console.error('There was an error', err);    return;  }  console.log(data);}fs.readFile('/some/file/that/does-not-exist', errorFirstCallback);fs.readFile('/some/file/that/does-exist', errorFirstCallback);

The JavaScript try / catch mechanism cannot be used to intercept errorsgenerated by asynchronous APIs. A common mistake for beginners is to try touse throw inside an error-first callback:

// THIS WILL NOT WORK:const fs = require('fs');try {  fs.readFile('/some/file/that/does-not-exist', (err, data) => {    // mistaken assumption: throwing here...    if (err) {      throw err;    }  });} catch (err) {  // This will not catch the throw!  console.error(err);}

This will not work because the callback function passed to fs.readFile() iscalled asynchronously. By the time the callback has been called, thesurrounding code (including the try { } catch (err) { } block will havealready exited. Throwing an error inside the callback can crash the Node.jsprocess in most cases. If [domains][] are enabled, or a handler has beenregistered with process.on('uncaughtException'), such errors can beintercepted.

Error 类#

一个通用的 JavaScript Error 对象,它不表示错误发生的具体情况。Error 对象会捕捉一个“堆栈跟踪”,详细说明被实例化的 Error 对象在代码中的位置,并可能提供错误的文字描述。

只对于加密,如果在抛出错误时可以使用 Error 对象,则会将OpenSSL错误堆栈放入到名为 opensslErrorStack 的单独属性中。

所有由 Node.js 产生的错误,包括所有系统的和 JavaScript 的错误都实例化自或继承自 Error 类。

new Error(message)#

  • message

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

Error.captureStackTrace(targetObject[, constructorOpt])#