错误冒泡和拦截
¥Error propagation and interception
Node.js 支持多种机制来传播和处理应用运行时发生的错误。如何报告和处理这些错误完全取决于 Error
的类型和调用的 API 的风格。
¥Node.js supports several mechanisms for propagating and handling errors that
occur while an application is running. How these errors are reported and
handled depends entirely on the type of Error
and the style of the API that is
called.
所有 JavaScript 错误都作为异常处理,使用标准 JavaScript throw
机制立即生成并抛出错误。这些是使用 JavaScript 语言提供的 try…catch
构造 来处理的。
¥All JavaScript errors are handled as exceptions that immediately generate
and throw an error using the standard JavaScript throw
mechanism. These
are handled using the try…catch
construct provided by the
JavaScript language.
// Throws with a ReferenceError because z is not defined.
try {
const m = 1;
const n = m + z;
} catch (err) {
// Handle the error here.
}
任何对 JavaScript throw
机制的使用都将引发必须使用 try…catch
处理的异常,否则 Node.js 进程将立即退出。
¥Any use of the JavaScript throw
mechanism will raise an exception that
must be handled using try…catch
or the Node.js process will exit
immediately.
除了少数例外,同步 API(任何不接受 callback
函数的阻塞方法,例如 fs.readFileSync
)将使用 throw
来报告错误。
¥With few exceptions, Synchronous APIs (any blocking method that does not
accept a callback
function, such as fs.readFileSync
), will use throw
to report errors.
异步 API 中发生的错误可能会以多种方式报告:
¥Errors that occur within Asynchronous APIs may be reported in multiple ways:
-
大多数接受
callback
函数的异步方法将接受作为第一个参数传给该函数的Error
对象。如果第一个参数不是null
并且是Error
的实例,则发生了应该处理的错误。¥Most asynchronous methods that accept a
callback
function will accept anError
object passed as the first argument to that function. If that first argument is notnull
and is an instance ofError
, then an error occurred that should be handled.const fs = require('node:fs'); fs.readFile('a file that does not exist', (err, data) => { if (err) { console.error('There was an error reading the file!', err); return; } // Otherwise handle the data });
-
当在
EventEmitter
对象上调用异步方法时,错误可以路由到该对象的'error'
事件。¥When an asynchronous method is called on an object that is an
EventEmitter
, errors can be routed to that object's'error'
event.const net = require('node:net'); const connection = net.connect('localhost'); // Adding an 'error' event handler to a stream: connection.on('error', (err) => { // If the connection is reset by the server, or if it can't // connect at all, or on any sort of error encountered by // the connection, the error will be sent here. console.error(err); }); connection.pipe(process.stdout);
-
Node.js API 中的一些典型的异步方法可能仍然使用
throw
机制来引发必须使用try…catch
处理的异常。没有此类方法的完整列表;请参考每种方法的文档以确定所需的适当错误处理机制。¥A handful of typically asynchronous methods in the Node.js API may still use the
throw
mechanism to raise exceptions that must be handled usingtry…catch
. There is no comprehensive list of such methods; please refer to the documentation of each method to determine the appropriate error handling mechanism required.
'error'
事件机制的使用最常见于 stream-based 和 基于事件触发器 API,它们本身代表随时间推移的一系列异步操作(与可能通过或失败的单个操作相反)。
¥The use of the 'error'
event mechanism is most common for stream-based
and event emitter-based APIs, which themselves represent a series of
asynchronous operations over time (as opposed to a single operation that may
pass or fail).
对于所有 EventEmitter
对象,如果没有提供 'error'
事件处理程序,将抛出错误,导致 Node.js 进程报告未捕获的异常并崩溃,除非:domain
模块使用得当或已为 'uncaughtException'
事件注册了处理程序。
¥For all EventEmitter
objects, if an 'error'
event handler is not
provided, the error will be thrown, causing the Node.js process to report an
uncaught exception and crash unless either: The domain
module is
used appropriately or a handler has been registered for the
'uncaughtException'
event.
const EventEmitter = require('node:events');
const ee = new EventEmitter();
setImmediate(() => {
// This will crash the process because no 'error' event
// handler has been added.
ee.emit('error', new Error('This will crash'));
});
以这种方式产生的错误无法使用 try…catch
拦截,因为它们是在调用代码已经退出后抛出的。
¥Errors generated in this way cannot be intercepted using try…catch
as
they are thrown after the calling code has already exited.
开发者必须参考每种方法的文档,以确定这些方法引发的错误是如何传播的。
¥Developers must refer to the documentation for each method to determine exactly how errors raised by those methods are propagated.