(1)同步错误处理
Node.js 中的同步错误处理与 JavaScript 是一样的,可以使用 try/catch/finally。
(2)异步错误处理:回调模式
对于异步代码,Node.js 强烈依赖两个术语:
1.事件发射器
2.回调模式
在回调模式中,异步 Node.js API 接受一个函数,该函数通过事件循环处理并在调用堆栈为空时立即执行。
来看下面的例子:
const { readFile } = require("fs");
function readDataset(path) {
readFile(path, { encoding: "utf8" }, function(error, data) {
if (error) console.error(error);
// data操作
});
}
这里可以看到回调中错误处理:
function(error, data) {
if (error) console.error(error);
// data操作
}
如果使用 fs.readFile 读取给定路径时出现任何错误,我们都会得到一个 error 对象。这时我们可以:
1.单地记录错误对象。
2.抛出异常。
3.将错误传递给另一个回调。
要想抛出异常,可以这样做:
const { readFile } = require("fs");
function readDataset(path) {
readFile(path, { encoding: "utf8" }, function(error, data) {
if (error) throw Error(error.message);
// data操作
});
}
但是,与 DOM 中的事件和计时器一样,这个异常会使程序崩溃。 使用 try/catch 停止它的尝试将不起作用:
const { readFile } = require("fs");
function readDataset(path) {
readFile(path, { encoding: "utf8" }, function(error, data) {
if (error) throw Error(error.message);
// data操作
});
}
try {
readDataset("not-here.txt");
} catch (error) {
console.error(error.message);
}
如果不想让程序崩溃,可以将错误传递给另一个回调:
const { readFile } = require("fs");
function readDataset(path) {
readFile(path, { encoding: "utf8" }, function(error, data) {
if (error) return errorHandler(error);
// data操作
});
}
这里的 errorHandler 是一个简单的错误处理函数:
function errorHandler(error) {
console.error(error.message);
// 处理错误:写入日志、发送到外部logger
}
(3)异步错误处理:事件发射器
Node.js 中的大部分工作都是基于事件的。大多数时候,我们会与发射器对象和一些侦听消息的观察者进行交互。
Node.js 中的任何事件驱动模块(例如 net)都扩展了一个名为 EventEmitter 的根类。EventEmitter 有两个基本方法:on 和 emit。
下面来看一个简单的 HTTP 服务器:
const net = require("net");
const server = net.createServer().listen(8081, "127.0.0.1");
server.on("listening", function () {
console.log("Server listening!");
});
server.on("connection", function (socket) {
console.log("Client connected!");
socket.end("Hello client!");
});
这里我们监听了两个事件:listening 和 connection。除了这些事件之外,事件发射器还公开一个错误事件,在出现错误时触发。
如果这段代码监听的端口是 80,就会得到一个异常:
const net = require("net");
const server = net.createServer().listen(80, "127.0.0.1");
server.on("listening", function () {
console.log("Server listening!");
});
server.on("connection", function (socket) {
console.log("Client connected!");
socket.end("Hello client!");
});
输出结果如下:
events.js:291
throw er;
^
Error: listen EACCES: permission denied 127.0.0.1:80
Emitted 'error' event on Server instance at: ...
为了捕获它,可以为 error 注册一个事件处理函数:
server.on("error", function(error) {
console.error(error.message);
});
这样就会输出:
listen EACCES: permission denied 127.0.0.1:80