细说setTimeout/setImmediate/process.nextTick的区别

node.js中的非IO的异步API提供了四种方法,分别为setTimeOut(),setInterval(),setImmediate()以及process.nextTick(),四种方法实现原理类似,但达到的效果略有区别:javascript

1、事件循环Event Loop

首先,咱们须要了解node.js的基于事件循环的事件模型,正是由于它才使得node.js中回调函数十分广泛,也正是基于此,node.js实现了单线程高效的异步IO(这里说的单线程主要说的是执行javascript代码部分的线程,而异步IO部分node.js其实仍是利用线程池去执行的)。css

简单的讲就是,在node.js启动时,建立了一个相似while(true)的循环体,每次执行一次循环体称为一次tick,每一个tick的过程就是查看是否有事件等待处理,若是有,则取出事件极其相关的回调函数并执行,而后执行下一次tick。因此,有以下代码:java

A(); B(); C();
  • 1
  • 2
  • 3

它的执行逻辑是,先询问事件观察者当前是否有任务须要执行?观察者回答“有”,因而取出A执行,A是否有回调函数?若是有(若是没有则继续询问当前是否有任务须要执行),则取出回调函数并执行(注意:回调函数的执行基本都是异步的,可能不止一个回调),执行完回调后经过某种方式通知调用者,我执行完了,并把执行结果给你,你本身酌情处理吧,主函数不须要不断询问回调函数执行结果,回调函数会以通知的方式告知调用者我执行完了(don’t call me ,i will call you.),而这个过程主线程并不须要等待回调函数执行完成,它会继续向前执行,即再次询问观察者当前是否还有任务须要执行,重复上面的步骤。。。直到观察者回答没有了,线程结束。node

整个事件循环的逻辑以下图:异步

这里写图片描述

二:setTimeOut(),setInterval(),setImmediate()以及process.nextTik()

这里面setTimeOut()与setInterval()除了执行频次外基本相同,都表示主线程执行完必定时间后当即执行,而setImmediate()与之十分类似,也表示主线程执行完成后当即执行。那么他们之间的区别是什么呢?函数

代码以下:oop

setTimeout(function(){ console.log("setTimeout"); },0); setImmediate(function(){ console.log("setImmediate"); });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

二者都表明主线程完成后当即执行,其执行结果是不肯定的,多是setTimeout回调函数执行结果在前,也多是setImmediate回调函数执行结果在前,但setTimeout回调函数执行结果在前的几率更大些,这是由于他们采用的观察者不一样,setTimeout采用的是相似IO观察者,setImmediate采用的是check观察者,而process.nextTick()采用的是idle观察者。spa

三种观察者的优先级顺序是:idle观察者>>io观察者>check观察者线程

process.nextTick()与setImmediate()和setTimeout()的区别以下:code

一、原始代码:

A(); B(); C();
  • 1
  • 2
  • 3

它的执行顺序即代码顺序:

这里写图片描述

二、process.nextTick()执行效果,代码以下:

A(); process.nextTick(B); C();
  • 1
  • 2
  • 3

它的执行顺序以下:

这里写图片描述

三、setImmediate()或者setTimeout()执行效果,代码以下:

A(); setImmediate(B);//或者setTimeout(B,0); C();
  • 1
  • 2
  • 3

它的执行顺序以下:

这里写图片描述

结论: process.nextTick(),效率最高,消费资源小,但会阻塞CPU的后续调用; setTimeout(),精确度不高,可能有延迟执行的状况发生,且由于动用了红黑树,因此消耗资源大; setImmediate(),消耗的资源小,也不会形成阻塞,但效率也是最低的。

相关文章
相关标签/搜索