node.js setImmediate意外行为

时间:2015-09-25 17:22:05

标签: node.js

据我了解,process.nextTick()setImmediate()之间存在以下差异:

  1. process.nextTick()安排的回调将在进入下一个事件循环之前执行,而由setImmediate()安排的回调将仅在每个事件循环中执行一次。
  2. 根据上述特征,可以说:process.nextTick()的递归调用会导致程序挂起,而setImmediate()的递归调用则不会。
  3. 然后我写了一些测试代码来验证上面的陈述,这是我的代码:

    process.nextTick(function() {
        console.log('nextTick1');
    });
    
    process.nextTick(function() {
        console.log('nextTick2');
    });
    
    setImmediate(function() {
        console.log('setImmediate1');
        process.nextTick(function() {
            console.log('nextTick3');
        });
    });
    
    setImmediate(function() {
        console.log('setImmediate2');
    });
    

    我的预期结果应为

      

    nextTick1,nextTick2,setImmediate1,nextTick3,setImmediate2

    ,但我实际得到的是

      

    nextTick1,nextTick2,setImmediate1,setImmedate2,nextTick3

    然后我又开了一个测试来研究setImmediate()的行为:

    //the following code is using express as the framework
    app.get('/test', function (req, res) {
        res.end('The server is responding.');
    });
    
    app.get('/nexttick', function (req, res) {
        function callback() {
            process.nextTick(callback);
        }
        callback();
        res.end('nextTick');
    });
    
    app.get('/setimmediate', function (req, res) {
        function callback() {
            setImmediate(callback);
        }
        callback();
        res.end('setImmediate');
    });
    

    第1步:我在浏览器上访问了http://localhost:3000/nexttick,我收到了文字nexttick

    步骤2:我访问http://localhost:3000/test以测试我的服务器是否仍在响应请求,并且我没有得到任何响应,浏览器一直在等待响应。这并不奇怪,因为process.nextTick()的递归调用已经挂起了服务器。

    Step3:我重启了服务器。

    第4步:我访问了http://localhost:3000/setimmediate并获得了文字setimmediate

    步骤5:我再次访问http://localhost:3000/test以测试我的服务器是否仍在响应。结果与Step2相同,我没有得到任何响应,浏览器一直在等待响应。

    这意味着process.nextTick()setImmediate()的行为几乎相同,但我知道它们不是。

    我想知道为什么会发生这种情况或者我误解了某事。谢谢。

    P.S。我在Windows 10下运行Node v0.12.7。

1 个答案:

答案 0 :(得分:0)

实际上你的测试结果看起来不错(我只参考第一个测试)。 你的评论“setImmediate()只会在每个事件循环中执行一次。”是错的,见https://nodejs.org/api/timers.html#timers_setimmediate_callback_arg 这就是你不理解第一次测试结果的原因。

基本上,process.nextTick会将你的函数放在当前事件循环的末尾,而setImmediate会将它放在下一个事件循环中。

但是执行多个setImmediate是可以的,他们都将转到同一个下一个事件循环。

setImmediate(function() {
    console.log('setImmediate1');
    process.nextTick(function() {
        console.log('nextTick3');
    });
});

setImmediate(function() {
    console.log('setImmediate2');
});

基本上你已经在下一个事件循环中调用了2个函数sthat,并且在其中一个中你放了另一个nextTick,它将在同一个循环结束时调用,但是在同一个循环结束时调用。 因此,它将首先调用那些2 setImmediate而不是第一个调用的nextTick。