![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/77baa5a25dbcef9007e2cc54a75e2756.png)
01
setTimeout、setInterval
setTimeout() 和 setInterval() 与浏览器中的API是一致的,分别用于单次和多次定时执行任务。它们的实现原理与异步I/O比较类似,只是不需要I/O线程池的参与。调用 setTimeout() 或者 setInterval() 创建的定时器会被插入到定时器观察者内部的一个红黑树中。事件循环每次执行时,会从该红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过,就形成一个事件,它的回调函数将立即执行。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/47b77b241664c6817ab4c38320c286d7.png)
定时器的问题在于,它并非精确的(在容忍范围内)。尽管事件循环十分快,但是如果某一次循环占用的时间较多,那么下次循环时,它也许已经超时很久了。譬如通过 setTimeout() 设定一个任务在10毫秒后执行,但是在9毫秒后,有一个任务占用了5毫秒的CPU时间片,再次轮到定时器执行时,时间就已经过期4毫秒。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/7c862320ce728ed4bcfe950d2c19f3ba.jpeg)
02
process.nextTick
由于事件循环自身的特点,定时器的精确度不够。而事实上,采用定时器需要动用红黑树,创建定时器对象和迭代等操作,而 setTimeout(fn, 0) 的方式较为浪费性能。实际上, process.nextTick() 方法的操作相对较为轻量每次调用 process.nextTick() 方法,只会将回调函数放入队列中,在下一轮事件循环时取出执行。定时器中采用红黑树的操作时间复杂度为 O(lg(n)) , nextTick()的时间复杂度为 O(1) 。相较之下, process.nextTick()更高效。
03
setImmediate
setImmediate() 方法与 process.nextTick() 方法十分类似,都是将回调函数延迟执行。
process.nextTick() 中的回调函数执行的优先级要高于 setImmediate() 。这里的原因在于事件循环对观察者的检查是有先后顺序的, process.nextTick() 属于idle观察者, setImmediate()属于check观察者。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/47b77b241664c6817ab4c38320c286d7.png)
推荐图书
技术决定你能走多快,数据结构和算法决定你能走多远。