Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它使用了一个事件驱动、非阻塞 I/O 模型,这使得 Node.js 成为轻量且高效的网络应用平台。
事件循环机制
Node.js 中的核心概念之一是事件循环。它是一个无限循环,处理所有的异步操作和事件。事件循环不断地检查事件队列,并执行队列中的回调函数。事件循环的主要阶段包括:
- timers:执行
setTimeout和setInterval回调。 - pending callbacks:执行一些系统操作的回调,如 TCP 错误。
- idle, prepare:仅内部使用。
- poll:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有回调,除了关闭回调、定时器回调)。
- check:执行
setImmediate的回调。 - close callbacks:执行关闭的回调,如
socket.on('close', ...)。
事件发射器
Node.js 提供了一个内置的 EventEmitter 类,用于处理事件驱动的应用程序。这个类位于 events 模块中。你可以通过以下方式使用它:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');常见事件处理方法
on(eventName, listener): 注册一个监听器到指定事件上。once(eventName, listener): 注册一个只触发一次的监听器。removeListener(eventName, listener): 移除指定事件的监听器。removeAllListeners([eventName]): 移除所有事件的所有监听器,或者如果指定的话,移除指定事件的所有监听器。setMaxListeners(n): 设置每个事件的最大监听器数量。
示例代码
下面是一个简单的例子,展示如何使用 EventEmitter 来创建自定义事件:
// www.javascriptcn.com code example
const EventEmitter = require('events');
class SalesEventEmitter extends EventEmitter {}
const salesEmitter = new SalesEventEmitter();
// 注册一个监听器
salesEmitter.on('newSale', (product, price) => {
console.log(`A new sale of ${product} for ${price} has been made.`);
});
// 触发事件
salesEmitter.emit('newSale', 'T-shirt', '$20');错误处理
在 Node.js 中,错误处理通常通过监听 'error' 事件来完成。如果你不处理这些事件,Node.js 将会抛出异常并退出程序。
// www.javascriptcn.com code example
const net = require('net');
const server = net.createServer((conn) => {
// 'error' 事件将在这里触发
conn.on('error', (err) => {
console.log(`Server error: ${err.message}`);
});
});
server.listen(8000, () => {
console.log('Server is listening on port 8000');
});流(Stream)
流是 Node.js 中处理数据的一种高效方法。它们可以是可读的、可写的或两者兼备的。流提供了事件驱动的 API,允许你在数据可用时立即处理它们,而不是等待所有数据都到达。
创建流
你可以通过以下方式创建流:
fs.createReadStream(path[, options])fs.createWriteStream(path[, options])process.stdin和process.stdout
流的事件
流对象是 EventEmitter 的实例,支持多种事件,如 data、end、error 等。
// www.javascriptcn.com code example
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
readStream.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes of data.`);
});
readStream.on('end', () => {
console.log('Read stream completed.');
});
readStream.on('error', (err) => {
console.error(`Error while reading the file: ${err.message}`);
});结语
通过理解 Node.js 的事件驱动模型,你可以更有效地构建响应迅速且资源高效的网络应用。掌握事件循环、事件发射器以及流的概念对于任何想要深入 Node.js 开发的人来说都是至关重要的。