最近在学习nodejs,看到了异步这块,就整理了下Node中几个异步APIjavascript
定时器:
setTimeout和setInterval与浏览器中的API是一致的,分别用于单次和屡次定时执行任务。他们的实现原理和异步I/O比较相似,只是不须要I/O线程池的参与。调用他们建立的定时器会被插入到定时器观察者内部的一个红黑树中。每次Tick执行的时候,会从该红黑树中迭代取出定时器对象,检查是否超过定时时间,若是超过,就造成一个事件,它的回调函数将当即执行。java
问题:并不是精确,尽管事件循环很是快,可是若是某一次循环占用的时间比较多,那么下次循环时,它也许已经超时好久了。node
process.nextTick()
不少人会为了当即异步执行一个任务,会这样调用setTimeout()来达到所需的效果。浏览器
setTimeout(function () {
// TODO
}, 0)
复制代码
因为事件循环的特色,定时器的精确度不够。而事实上,采用定时器须要动用红黑树,建立定时器对象和迭代等操做,而setTimeout(fn, 0)较为浪费性能。而process.nextTick()方法的操做相对较为轻量,具体代码以下:bash
process.nextTick = function (callback) {
if( process._exiting ) return;
if( tickDepth >= process.maxTickDepth ){
maxTickWarn();
}
var tock = { callback: callback};
if( process.domain ) tock.domain = process.domain;
nextTickQueue.push( tock );
if( nextTickQueue.length ) {
process._needTickCallback();
}
}
复制代码
每次调用process.nextTick()方法,只会将回调函数放入队列中,在下一轮Tick时取出执行。定时器中采用红黑树的操做时间复杂度为O(lg(n)), nextTick()的时间复杂度为O(1)。相对之下,process.nextTick()更加有效。dom
setImmediate()
setImmdiate()方法与process.nextTick()方法相似,都是将回调函数延迟执行。异步
process.nextTick( function () {
console.log("延迟执行!");
});
console.log("正常执行!");
// 结果:
// 正常执行
// 延迟执行
复制代码
用setImmediate()实现:函数
setImmediate( function () {
console.log("延迟执行")
});
console.log("正常执行");
// 结果:
// 正常执行
// 延迟执行
复制代码
放在一块儿执行:性能
proccess.nextTick( function () {
console.log("nextTick");
});
setImmediate( function () {
console.log("immediate");
});
console.log("正常执行");
// 结果:
// 正常执行
// nextTick
// immediate
复制代码
process.nextTick()中的回调函数优先级高于setImmediate(). process.nextTick()属于idle观察者,setImmediate()属于check观察者。在每个轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者。学习
三者的执行顺序为process.next() 先于 定时器 先于 setImmediate()