
上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 连接成功。 数据接收成功。 程序执行完毕。