【问题标题】:Node.js: http.request() triggers after setImmediate()Node.js:http.request() 在 setImmediate() 之后触发
【发布时间】:2018-02-02 22:25:43
【问题描述】:

我是 Node 新手,所以我不清楚以下代码行为:

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);

输出:

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() 是一个 check 阶段,应该在 poll 之后在事件循环中处理。如果我理解正确,nextTick() 之后的http.request() 应该是那个 poll 阶段;

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

我的 Node.js 版本是 6.11.2。提前感谢您的解释。

【问题讨论】:

  • 它稍后会记录它,因为它正在等待响应

标签: javascript node.js event-loop setimmediate


【解决方案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);

在那个 sn-p 中,我删除了 nextTick,不过如果需要,您可以安全地将其添加到回调中。

【讨论】:

  • 虽然http.request() 被首先调用,但回调直到稍后的时间点才记录任何内容——并且该时间点是在setImmediate() 解决之后。 - 可以请给个文档链接好吗?
  • 因为我读过the opposite如果轮询队列(我假设http.request() 在那个队列中)不为空,事件循环将遍历其同步执行它们的回调队列...如果脚本已由 setImmediate() 调度,则事件循环将结束轮询阶段并继续检查阶段以执行那些已调度的脚本。 因此,我建议回调请求将更早触发,即setImmediate 的。
  • 您链接到的文档是正确的,但它不适用于传递给.request() 的回调。在nodejs.org/api/http.html#http_http_request_options_callback 下,它指出:“可选的回调参数将被添加为‘response’事件的一次性监听器。”即使.request() 被立即执行,响应也会被异步接收。如果您在request 上侦听立即回调,您可以看到这一点,例如request.on('socket', ...),它似乎是同步的,并且在setImmediate 之前记录。
猜你喜欢
  • 2016-10-30
  • 1970-01-01
  • 2016-05-30
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
相关资源
最近更新 更多