错误冒泡和拦截
¥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
机制的任何使用都会引发必须处理的异常,否则 Node.js 进程将立即退出。
¥Any use of the JavaScript throw
mechanism will raise an exception that
must be handled or the Node.js process will exit immediately.
除了少数例外,同步 API(任何不返回 <Promise> 也不接受 callback
函数的阻塞方法,例如 fs.readFileSync
)将使用 throw
来报告错误。
¥With few exceptions, Synchronous APIs (any blocking method that does not
return a <Promise> nor 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:
-
某些异步方法返回 <Promise>,你应该始终考虑到它可能会被拒绝。请参阅
--unhandled-rejections
标志,了解进程如何对未处理的 promise 拒绝做出反应。¥Some asynchronous methods returns a <Promise>, you should always take into account that it might be rejected. See
--unhandled-rejections
flag for how the process will react to an unhandled promise rejection.const fs = require('node:fs/promises'); (async () => { let data; try { data = await fs.readFile('a file that does not exist'); } catch (err) { console.error('There was an error reading the file!', err); return; } // Otherwise handle the data })();
-
大多数接受
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 进程报告未捕获的异常并崩溃,除非:已为 'uncaughtException'
事件注册了处理程序,或者使用了已弃用的 node:domain
模块。
¥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: a handler has been registered for
the 'uncaughtException'
event, or the deprecated node:domain
module is used.
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.