Node为服务端JavaScript提供了一个事件驱动的、异步的平台。它把JavaScript带到服务端中的方式跟浏览器把JavaScript带到客户端的方式几乎一模一样。了解浏览器的工作原理对我们了解Node的工作原理会有很大帮助。它们都是事件驱动(用事件轮询)和非阻塞的I/O处理(用异步I/O)。下面举个例子说明这是什么意思。 事件轮询和异步I/O 要了解更多有关事件轮询和异步I/O的知识,请参见相关的维基百科文章:http://en.wikipedia.org/wiki/Event_loop和http://en.wikipedia.org/wiki/Asynchronous_I/O。 我们来看一小段jQuery用XMLHttpRequest(XHR)做Ajax请求的代码: 这个程序会发送一个到resource.json的HTTP请求。当响应返回时会调用带着参数data的匿名函数(在这个上下文中的“回调函数”),data就是从那个请求中得到的数据。 注意,代码没有写成下面这样: 在这个例子中,假定对resource.json的响应在准备好后会存储在变量data中,并且在此之前函数console.log不会执行。I/O操作(Ajax请求)会“阻塞”脚本继续执行,直到数据准备好。因为浏览器是单线程的,如果这个请求用了400ms才返回,那么页面上的其他任何事件都要等到那之后才能执行。可以想象一下,如果一幅动画被停住了,或者用户试着跟页面交互时动不了,那种用户体验有多糟糕。 谢天谢地,实际情况不是这样的。当浏览器中有I/O操作时,该操作会在事件轮询的外面执行(脚本执行的主顺序之外),然后当这个I/O操作完成时,它会发出一个“事件”, 会有一个函数(通常称作“回调”)处理它,如图1-1所示。 这个I/O是异步的,并且不会“阻塞”脚本执行,事件轮询仍然可以响应页面上执行的其他交互或请求。这样,浏览器可以对客户做出响应,并且可以处理页面上的很多交互动作。 请牢记上面这些内容,现在我们切换到服务端。 图1-1 浏览器中非阻塞I/O的例子