手记

Nodejs提炼与升华(三) Nodejs快速入门 PART2

3.2 异步式IO与事件式编程

3.2.1 异步式IO

现在把整个服务器想象成餐馆,客人代表请求,服务员代表线程,点餐代表耗时的IO操作。

PHP式的同步式IO经营的场景是这样的:当客人A来就餐的时候,服务员甲带领客人入座,然后客人A点菜,服务员甲就在旁边等候。正在这时,客人B来了,因为服务员甲在等候A客人点餐,所以老板只能又派出一名服务员乙去带领客人B入座,然后客人B点菜,服务员乙在旁边等候。我相信你能想象到客人C、D、E来到的情景了。

而Nodejs餐厅的经营方式看起来更受小成本饭店老板的青睐:客人A来就餐,服务员甲带领客人入座,然后客人A点餐。如果这时客人B也来就餐,服务员甲就会给客人A说:”请您先选着,选好了叫我“,然后他就会去带领客人B就坐,让客人B点餐。等客人A点餐结束后,服务员甲在从A那里收菜单,告诉厨房做什么食物。以此类推,有多位客人同时就餐的场景你也可以想象的到。

Nodejs最大的特点就是异步式IO(非阻塞式IO)与事件紧密结合的编程模式。这种模式和传统的同步式IO线性编程思路有很大的不同,因为控制流在很大程度上要靠事件和回调函数来组织,一个逻辑要拆分成若干的单元。

当异步式IO采取单线程模式。遇到耗时的IO操作时,不会以阻塞的方式等待IO操作的完成或者数据的返回,而是将I/O请求发送给操作系统,继续执行下一条语句。当操作系统完成IO操作时,以事件的形式通知IO操作的线程,线程会在特定的时候处理这个事件。为了处理异步IO,线程必须有事件循环,依次检查有没有未处理的事件依次予以处理。

异步式IO的优点在于减少了多线程昂贵的开销;缺点则在于不读和人们一般的程序设计思维,容易让控制流程变得晦涩难懂,给编码和调试带来不少困难。现在已经有很多库(比如async)来帮助我们解决这个问题。

究竟哪种方式好,现在阻塞和非阻塞的双方还争执不下。

3.2.2 Nodejs事件循环机制

Nodejs的异步机制是基于事件的,所有的异步IO操作在完成时都会发送一个事件给事件队列。在开发者看来,事件由EventEmitter对象提供。Nodejs的程序由事件循环开始,到事件循环结束。所有的逻辑都是事件的回调函数,所以nodejs始终在事件循环中。程序入口就是事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出IO请求或直接发射事件(直接发射的事件如果没有IO请求则不会进入事件队列,也就是说普通的事件发射按正常顺序逻辑执行),执行完毕后再返回事件循环,事件循环会检查事件队列中有没有为处理的事件,直到程序结束。

Nodejs进程在同一时刻只能处理一个事件,完成后立即进入事件循环并处理后面的事件。

Nodejs中没有显式的事件循环,其事件循环对开发者是不可见的,由libev库实现。libev不断检查是否有活动的、可供检测的事件监听器,直到检测不到时才会退出事件循环,进程结束。

我们将在4.3节详细的谈一谈Nodejs的最重要模块——events模块。Hey,你为何不提前跳到4.3节看一看呢?

3人推荐
随时随地看视频
慕课网APP