错误的冒泡和捕捉
所有的 JavaScript 错误都是作为异常处理的,立即产生并通过标准的 JavaScript throw
机制抛出错误。这些都是利用 JavaScript 语言提供的 处理的。
JavaScript 的 throw
机制在任何时候使用都会引发异常,必须通过 try / catch
处理,否则 Node.js 会立即退出进程。
但也有少数例外,同步的 API(任何不接受 callback
函数的阻塞方法,例如,fs.readFileSync)会使用 throw
报告错误。
- 大多数的异步方法都接受一个
callback
函数,该函数接受给其第一个参数传递一个Error
对象。如果第一个参数不是null
或是一个Error
实例,就应该对发生的错误进行处理。
const fs = require('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
});
- 在 Node.js API 中有一小部分普通的异步方法仍可能使用
throw
机制引发错误,必须使用try / catch
处理。这些方法并没有一个完整的列表。请参阅各类方法的文档以确定所需的合适的错误处理机制。
大多数的 和 event emitter-based API 都使用相同的 'error'
事件机制,它们本身就代表了一系列随着时间推移的异步操作(相对于单一操作,可能有效也可能无效)。
对于所有的 EventEmitter
对象而言,如果不能提供一个 'error'
事件处理程序,那么错误将被抛出,从而导致 Node.js 进程报告一个未处理的异常并随即崩溃,除非适当的使用 模块或已经注册了 process.on(‘uncaughtException’) 事件。
const EventEmitter = require('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
截获。
大多数由 Node.js 核心 API 暴露出来的异步方法都遵循称之为“Node.js 风格的回调”的惯用模式。通过这种模式,可以用作为参数的方法传递函数。当操作完成或引发错误时,Error
对象(无论如何)都会作为第一个参数被回调函数所调用。如果没有引发错误,第一个参数会作为 null
传递。
// 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.log(err);
}
这并没有什么用,因为 fs.readFile()
是一个异步调用的回调函数。当回调函数被调用时,这些代码(包括 try { } catch(err) { }
区域)就已经退出。在大对数案例中,抛出回调函数中的错误会引起 Node.js 进程崩溃。如果被启用,或已注册了 process.on(‘uncaughtException’) 事件,那么这样的错误是可以被拦截的。