Node.js是单线程的,基于事件循环,非阻塞 IO的。事件循环中使用一个事件队列,在每一个时间点上,系统只会处理一个事件,即便电脑有多个CPU核心,也没法同时并行的处理多个事件。所以,node.js适合处理I/O型的应用,不适合那种CPU运算密集型的应用。在I/O型的应用中,给每个输入输出定义一个回调函数,node.js会自动将其加入到事件轮询的处理队列里,当I/O操做完成后,这个回调函数会被触发,系统会继续处理其余的请求。 javascript
在这里用debuggable.com上的那个文章中的一段比喻来说,很是容易理解。以下: java
咱们写的js代码就像是一个国王,而nodejs给国王提供了不少仆人。早上,一个仆人叫醒了国王,问他有什么须要。国王给他一份清单,上面列举了全部须要完成的任务,而后睡回笼觉去了。当国王回去睡觉以后,仆人才离开国王,拿着清单,给其它的仆人一个个布置任务。仆人们各自忙各自的去了,直到完成了本身的任务后,才回来把结果禀告给国王。国王一次只召见一我的,其它的人就在外面排着队等着。国王处理完这个结果后,可能给他布置一个新的任务,或者就直接让他走了,而后再召见下一我的。等全部的结果都处理完了,国王就继续睡觉去了。直接有新的仆人完成任务后过来找他。这就是国王的幸福生活。 node
process.nextTick(callback) c++
功能:在事件循环的下一次循环中调用 callback 回调函数。效果是将一个函数推迟到代码书写的下一个同步方法执行完毕时或异步方法的事件回调函数开始执行时;与setTimeout(fn, 0) 函数的功能相似,但它的效率高多了。 git
基于node.js的事件循环分析,每一次循环就是一次tick,每一次tick时,v8引擎从事件队列中取出全部事件依次进行处理,若是遇到nextTick事件,则将其加入到事件队尾,等待下一次tick到来时执行;形成的结果是,nextTick事件被延迟执行;如下是nextTick源码 github
从这几行代码中,咱们能够看出不少信息: 多线程
下面看一下应用场景(包含计算密集型操做,将其进行递归处理,而不阻塞进程): 异步
一、其中compute是一个密集计算的函数,咱们把它变为可递归的,每一步须要1秒(使用wait来代替密集运行)。执行完一次后,经过process.nextTick把下一次的执行放在队列的尾部,转而去处理已经处于等待中的客户端请求。这样就能够同时兼顾两种任务,让它们都有机会执行。 函数
关于node.js中处理计算密集型,能够参考如下几种方法: oop
二、另外:异步模型的关系,致使某些代码的执行可能先于它们所须要的条件完成以前,因此将这些须要先置条件的代码放入到一个回调函数中,而后放入到下一个事件循环的顶层。那么这些代码就不会被马上执行了,而是在下一轮事件启动以前等待,启动后在进行执行。
范例:
var MyConstructor = function() { ... process.nextTick(function() { self._continue(); }); }; MyConstructor.prototype.__proto__ = EventEmitter.prototype; MyConstructor.prototype._continue = function() { // without the process.nextTick // these events would be emitted immediately // with no listeners. they would be lost. this.emit('data', 'hello'); this.emit('data', 'world'); this.emit('end'); }; function(req, res, next) { var c = new MyConstructor(...); c.on('data', function(data) { console.log(data); }); c.on('end', next); }