2017-08-24 112 views
-1

我在节点是新的,所以下面的代码的行为是不明确的对我说:的Node.js:()setImmediate后http.request()触发

function step(iteration) { 
    if (iteration === 10) return; 

    process.nextTick(() => { 
    step(iteration + 1); // Recursive call from nextTick handler. 
    console.log(`nextTick iteration: ${iteration}`);  
    }); 

    http.request({hostname: '127.0.0.1', port: 5000}, (response) => { 
    console.log("here !"); 
    }).end(); 

    setImmediate(() => { 
    console.log(`setImmediate iteration: ${iteration}`);  
    }); 
} 
step(0); 

OUTPUT:

nextTick iteration: 0 
... 
nextTick iteration: 9 
setImmediate iteration: 0 
... 
setImmediate iteration: 9 
here ! 
here ! 
here ! 
here ! 
here ! 
here ! 
here ! 
here ! 
here ! 
here ! 

问题是:

1)为什么http.request()回调是在setImmediate()之后触发的?我不明白,为什么setImmediate()通常被称为:它的回调是在循环中注册的。但正如文件所述,setImmediate()检查阶段,应该在事件循环后处理轮询一。如果我理解正确,http.request()nextTick()应该是轮询阶段;

2)但是如果http.request()没有在轮询中处理,它发生在什么阶段?特别是考虑到它在setImmediate()之后有效。

我的Node.js版本是6.11.2。预先感谢您的解释。

+0

它稍后记录它,因为它正在等待*响应* – 2017-08-24 22:31:51

回答

-1

回答您的问题:

  1. http.request()setImmediate()之前调用。但是,http.request是异步的。在你的情况下,直到请求解析后才会运行回调。这意味着虽然它被称为第一个,但回调不会记录任何事情,直到稍后的时间点 - 并且该点在setImmediate()解决之后。
  2. 尽管setImmediate将它的回调按其排队顺序排队执行,但它们仍然能够在请求返回前解析。

为了处理为了你的脚步,考虑移动nextTick内容的回调中的请求:

function step(iteration) { 
    if (iteration === 10) return; 

    http.request({hostname: '127.0.0.1', port: 8000}, (response) => { 
    console.log("here !"); 

    step(iteration + 1); // Recursive call from nextTick handler. 

    console.log(`nextTick iteration: ${iteration}`);  
    }).end(); 

    setImmediate(() => { 
    console.log(`setImmediate iteration: ${iteration}`);  
    }); 
} 
step(0); 

在该片段中,我已经去除了nextTick,虽然你如果需要可以安全地将其添加到回调中。

+0

_尽管先调用'http.request()',回调不记录任何内容,直到稍后的时间点 - 并且该点位于' setImmediate()'已经解决了._ - 你能给出一个关于文档的链接吗? –

+0

因为我读过[反面](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#poll):_如果轮询queue_(我认为,http。 request()'在该队列中)_is不为空​​,则事件循环将遍历其同步执行它的回调队列。如果脚本已由setImmediate()调度,则事件循环将结束轮询阶段并继续执行这些预定脚本的检查阶段。因此,我建议早期触发请求的回调,即setImmediate是一个。 –

+0

您链接到的文档是正确的,但它不适用于传递给'.request()'的回调。在https://nodejs.org/api/http.html#http_http_request_options_callback下,它注意到:“可选的回调参数将作为'响应'事件的一次性侦听器添加。” 即使通过'。request()'正在被立即执行,响应被异步接收。你可以看到这个,如果你听到'request'的即时回调,比如'request.on('socket',...)',它似乎是同步的,并且记录在'setImmediate'之前。 – Hans

相关问题