Page 42 - Node.js开发指南
P. 42

3.2  异步式 I/O 与事件式编程    33


                                                                                                      1
                                  Node.js 中,并不是所有的 API 都提供了同步和异步版本。Node.js 不
                              鼓励使用同步 I/O。


               3.2.3 事件                                                                               2

                   Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。在开发者看来,事
               件由 EventEmitter 对象提供。前面提到的 fs.readFile 和 http.createServer 的回
                                                                                                      3
               调函数都是通过 EventEmitter 来实现的。下面我们用一个简单的例子说明 EventEmitter
               的用法:

                   //event.js
                                                                                                      4
                   var EventEmitter = require('events').EventEmitter;
                   var event = new EventEmitter();

                   event.on('some_event', function() {
                     console.log('some_event occured.');
                   });                                                                                5

                   setTimeout(function() {
                     event.emit('some_event');
                   }, 1000);
                                                                                                      6
                   运行这段代码,1秒后控制台输出了 some_event occured.。其原理是 event 对象

               注册了事件  some_event 的一个监听器,然后我们通过  setTimeout 在1000毫秒以后向
               event 对象发送事件 some_event,此时会调用 some_event 的监听器。
                   我们将在 4.3.1节中详细讨论 EventEmitter 对象的用法。                                               7
                   Node.js 的事件循环机制
                   Node.js 在什么时候会进入事件循环呢?答案是 Node.js 程序由事件循环开始,到事件循
               环结束,所有的逻辑都是事件的回调函数,所以 Node.js 始终在事件循环中,程序入口就是
                                                                                                      8
               事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出 I/O 请求或
               直接发射(emit)事件,执行完毕后再返回事件循环,事件循环会检查事件队列中有没有未
               处理的事件,直到程序结束。图3-5说明了事件循环的原理。
                   与其他语言不同的是,Node.js 没有显式的事件循环,类似 Ruby 的 EventMachine::run()                          9

               的函数在 Node.js 中是不存在的。Node.js 的事件循环对开发者不可见,由 libev 库实现。libev
               支持多种类型的事件,如 ev_io、ev_timer、ev_signal、ev_idle 等,在 Node.js 中均被
               EventEmitter 封装。libev 事件循环的每一次迭代,在 Node.js 中就是一次 Tick,libev 不
                                                                                                      10
               断检查是否有活动的、可供检测的事件监听器,直到检测不到时才退出事件循环,进程结束。
   37   38   39   40   41   42   43   44   45   46   47