cnode论坛看到两个问题
参考链接
Understanding process.nextTick()
上一篇博客的中文翻译
Node.js API process
深入浅出Node.js 初探Node.js的异步I/O实现
需求
手动实现异步(用最顶层的方法)
错误思路
错误解决方案 1
乍一看,这不是很典型的异步写法么?(针对像我这种菜鸟,高手只能呵呵了),执行,却发现先输出f1,然后输出f2. 非常的不服,用更‘高端’的方法给出错误方案21
2
3
4
5
6
7
8
9function asynchronous(data, callback) {
callback(data);
}
asynchronous('f1', function(data) {
console.log(data);
});
console.log('f2');错误解决方案 2
看起来这段代码采用是事件监听和发射的机制,更加接近常见的异步式写法了,执行,发现还是先输出f1,然后输出f2.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18var util = require('util');
var events = require('events');
function eventEmitter() {
events.EventEmitter.call(this);
}
util.inherits(eventEmitter, events.EventEmitter);
var ee = new eventEmitter();
ee.on('data', function(data) {
console.log(data);
});
ee.emit('data', 'f1');
console.log('f2');
正确解法
正确解法 1
这种写法看起来很好理解,如果把setTimeout的0改为大于0的值看似更好理解,而且结果的确先输出了f2,然后输出了f1. 先来看正确解法2,再做解释1
2
3
4
5
6
7
8
9
10
11function asynchronous(data,callback) {
setTimeout(function(){
callback(data);
},0);
}
asynchronous('f1', function(data){
console.log(data);
});
console.log('f2');正确解法2
这是种相当推荐的写法,为什么能实现异步的效果呢?1
2
3
4
5
6
7
8
9
10
11function test(data,callback) {
process.nextTick(function(){
callback(data);
});
}
test('f1', function(data){
console.log(data);
});
console.log('f2');
说明
Once the current event loop turn runs to completion, call the callback function.,这是Node.js官网上的一句话,说明了,process.nextTick(callback)
中的callback会在当前的事件循环队列执行结束后,准备开始新的事件循环的时候执行,这样就实现异步操作了。如下图所示的Node.js事件循环
回到我们最初的问题,如果我们不使用process.nextTick(callback)
,上面两个错误的解法就成了看似异步方法的同步方法了。
官网上的另外一句话,This is not a simple alias to setTimeout(fn, 0), it’s much more efficient. It runs before any additional I/O events (including timers) fire in subsequent ticks of the event loop.这下我们就大概可以理解为什么setTimeOut也有类似的功能了,其实原理都是一样的。
这里引用一段话来详细描述一下process.nextTick()
这个方法
More precisely, process.nextTick() defers the function until a completely new stack. You can call as many functions as you want in the current stack. The function that called nextTick has to return, as well as its parent, all the way up to the root of the stack. Then when the event loop is looking for a new event to execute, your nextTick’ed function will be there in the event queue and execute on a whole new stack.
看不太懂英文的朋友勉强看下这段翻译吧
更精确的说,process.nextTick()定义的调用会创建一个新的子堆栈。在当前的栈里,你可以执行任意多的操作。但一旦调用netxTick,函数就必须返回到父堆栈。然后事件轮询机制又重新等待处理新的事件,如果发现nextTick的调用,就会创建一个新的栈。
建议大家好好看下Understanding process.nextTick()这篇博客,肯定会对process.nextTick()
这个方法有更深刻的理解