NodeJS 一显著特点是它的异步处理特性。例如,当我读入一个文件时,Node会将文件读取操作放在后台处理,当程序提交读取请求后,不必堵塞在原地等待请求完成,而是提供一个请求完成的回调函数,然后接着进行其他工作,一旦文件读取完成后,我们提供的函数会被及时调用,在回调函数中,再对读到的文件内容进行处理。正是由于这种异步处理机制,使得Node成为后台开发的一大利器,特别是其异步处理框架提供的高效率,使得它最近成为web后台开发的重要选择。
但是,灵活性是有成本的,异步处理模式提高了程序设计逻辑的复杂性,一旦稍有粗心大意,异步流程会导致一些难以察觉的bug, 例如下面的例子:
var EventEmitter = require('events').EventEmitter; function doSomeThingSlow() { var events = new EventEmitter(); events.emit('success'); return events; } doSomeThingSlow().on('success', function() { console.log('success!'); });
解决该问题的方法是,利用 Node的异步处理机制,将events.emit('success') 这一触发动作放入到消息队列中异步执行:
var EventEmitter = require('events').EventEmitter; function doSomeThingSlow() { var events = new EventEmitter(); process.nextTick(function() { events.emit('success'); }); return events; } doSomeThingSlow().on('success', function() { console.log('success!'); });
所以,如果运行上一个程序,我们在控制台看不到打印信息,运行第二个程序,我们才能看到打印信息。此类bug比较诡异,如果对Node的异步处理机制理解不深的话,就很难发现这种问题。