Node 中的非 I/O 的异步 API,它们分别是 setTimeout()
、setInterval()
、setImmediate()
和 process.nextTick()
。
定时器
setTimeout()
、setInterval()
与浏览器中的API是一致的,分别用于单次和多次定时执行任务。
缺点:定时器可能出现超时执行。例如通过setTimeout()设定一个任务在10毫秒后执行,但是在9好秒后,有一个任务占用了5毫秒的CPU时间片,再次轮到定时器执行时,时间就已经过期4毫秒。
process.nextTick()
在不了解 process.nextTick()
前,如果你为了立即异步执行一个任务,会这样调用 setTimeout()
来达到所需效果:
setTimeout(function() {
//TODO
}, 0);
由于事件循环自身的特点,定时器的精确度不够。而且采用定时器需要动用红黑树,创建定时器对象和迭代等操作,而 setTimeout(fn, 0)
的方式较为浪费性能。这时可以使用 process.nextTick()
方法,较为轻量级,具体代码如下:
process.nextTick = function() {
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)。
setImmediate()
setImmediate()
与 process.nextTick()
十分类似,都是将回调函数延迟执行。
process.nextTick(function () {
console.log('nextTick延迟执行1');
process.nextTick(function() {
console.log('插入1');
});
});
process.nextTick(function () {
console.log('nextTick延迟执行2');
});
setImmediate(function () {
console.log('setImmediate延迟执行1');
process.nextTick(function () {
console.log('插入2');
});
});
setImmediate(function () {
console.log('setImmediate延迟执行2');
});
console.log('正常执行');
输出
正常执行
nextTick延迟执行1
nextTick延迟执行2
插入1
setImmediate延迟执行1
setImmediate延迟执行2
插入2
以上是读《深入浅出Node.js》一书的一些记录。