我与Node.js中的计时器和异步I / O混淆了

时间:2017-08-06 09:42:23

标签: node.js timer libuv

这是一个例子:

const http = require('http');

let startTime = Date.now();

http.createServer((req,res)=>{
    console.log('hello');
    res.end('nice');
}).listen(8888,()=>{
    console.log('server listened at port 8888');
});


setTimeout(function() {
    console.log('hei,I am 5000 timeout function' + `time past ${Date.now()-startTime}`);
}, 5000);

setImmediate(()=>{
    console.log('hei,I am immediate function' + `time past ${Date.now()-startTime}`);
})

结果:

server listened at port 8888
hei,I am immediate functiontime past 14
hei,I am 5000 timeout functiontime past 5016

但是在我看来,setImmediate回调应该在5000ms之后运行,因为http异步网络I / O应该阻止事件循环5000ms,因为超时是由setTimeout设置的。但结果显示I/O pool阶段的事件循环立即返回。为什么?事件循环中的代码:

    timeout = 0;
    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
      timeout = uv_backend_timeout(loop);

    uv__io_poll(loop, timeout);
    uv__run_check(loop);
uv_backend_timeout()中的

diff = handle->timeout - loop->time;
  if (diff > INT_MAX)
    diff = INT_MAX;

  return diff;

因此I/O pool中的超时应为5000毫秒,然后uv_epoll_wait()应阻止事件循环5000毫秒,然后转到check阶段。所以我很困惑为什么setImmediate回调如此早地运行。

1 个答案:

答案 0 :(得分:0)

setTimeout函数是nodejs中的非阻塞函数。它不会阻止主事件循环。如果你真的想阻止事件循环,那么使用wait函数。