Node.js 12实战
上QQ阅读APP看书,第一时间看更新

2.8 事件循环

Node.js基本上所有的事件机制都是使用设计模式中的观察者模式实现的。Node.js单线程类似于进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生,就调用该回调函数。

Node.js使用事件驱动模型,当Web Server接收到请求时,就把它关闭,然后进行处理,接着去服务下一个Web请求。当这个请求完成后,它被放回处理队列,当到达队列开头后,这个结果被返回给用户。

这个模型非常高效,可扩展性非常强,因为Web Server一直接受请求而不等待任何读写操作。这也被称为非阻塞式IO或者事件驱动IO。

在事件驱动模型中会生成一个主循环来监听事件,当检测到事件时触发回调函数。

整个事件驱动的流程如图2.2所示。事件循环模型非常简洁,类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

图2.2 事件驱动的流程

Node.js有多个内置的事件,我们可以通过引入events模块,并通过实例化EventEmitter类来绑定和监听事件,示例如下:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

以下程序绑定事件处理程序:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);

我们可以通过程序触发事件:

// 触发事件
eventEmitter.emit('eventName');

【示例2-8】完整的示例代码如下,创建main3.js文件:

// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
   console.log('连接成功。');
   // 触发 data_received 事件
   eventEmitter.emit('data_received');
}
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
   console.log('数据接收成功。');
});
// 触发 connection 事件
eventEmitter.emit('connection');
console.log("程序执行完毕。");

接下来执行以上代码,结果如下:

$ node main3.js
连接成功。
数据接收成功。
程序执行完毕。