Node.js是否对setTimeout强制执行最小延迟?

时间:2011-08-28 14:16:30

标签: javascript node.js settimeout

在浏览器中,如果您在setTimeout调用的函数中使用setTimeout,则会强制执行最小延迟4毫秒。 Mozilla的开发人员wiki describes this behaviour,并提到它有become standardized in HTML5

Node.js的documentation for setTimeout未提及最小延迟。但是,the process.nextTick function的文档将其描述为setTimeout(fn, 0)的更有效替代方案。这表明它更有效的可能性,因为它避免了这种延迟。否则,setTimeout(fn, 0)可能会被优化为行为相同。

Node.js是否像web浏览器一样强制执行setTimeout的最小延迟?

3 个答案:

答案 0 :(得分:21)

它没有最小延迟,这实际上是浏览器和节点之间的兼容性问题。定时器完全没有在JavaScript中指定(它是一个DOM规范,在Node中没有用,甚至连浏览器都没有),节点实现它们只是因为它们在JavaScript的历史中有多么基础,以及它们在其他方面是多么不可替代。

Node使用libuv,这是一个跨平台抽象层,用于较低级别的系统事务,如文件系统,网络设备等。其中一个是定时器,Node提供最小的包装器。在libuv级别,使用的定时器是系统特定的高精度定时器。例如,在Windows中,这是使用QueryPerformanceFrequencyFileTimeToSystemTime实现的,它提供以纳秒为单位的分辨率。

在Node中,如果指定setTimeout(callback, 1),那么它将在一毫秒之后执行(假设系统因为不堪重负而没有延迟)。在浏览器中,HTML5规范指定的最短时间为4毫秒:https://developer.mozilla.org/en/DOM/window.setTimeout。这不是保证时间,只是最低限度。大多数浏览器的分辨率约为15毫秒,这会影响DOM动画。

一个有效的信息是在同一帧中设置为相同毫秒的超时将按照它们排队的顺序执行。如果你这样做:

  setTimeout(callback1, 1);
  setTimeout(callback2, 1);
  setTimeout(callback3, 1);
  setTimeout(callback4, 1);

在一个块中,Node应该按顺序调用它们。这仅适用于具有完全相同的解决时间的情况。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724280(v=vs.85).aspx

答案 1 :(得分:15)

从这次测试来看,它似乎没有最小的延迟。

如果您执行的setTimeout()持续时间为10ms,并且返回控制台的值很长,那就是您所得到的:

 var timer = setTimeout(function(){ console.log(timer);}, 10);

 { _idleTimeout: 10,
  _onTimeout: [Function],
  _idlePrev: null,
  _idleNext: null,
  _idleStart: Sun, 28 Aug 2011 14:34:41 GMT } 

同样,持续时间为1ms,您会得到:

 var timer = setTimeout(function(){ console.log(timer);}, 1);

 { _idleTimeout: 1,
  _onTimeout: [Function],
  _idlePrev: null,
  _idleNext: null,
  _idleStart: Sun, 28 Aug 2011 14:34:59 GMT } 

但是如果你持续0个持续时间,你根本就没有得到_idleTimeout:属性,这似乎表明回调是立即调用的,虽然是异步的。

var timer = setTimeout(function(){ console.log(timer);}, 0);

{ repeat: 0, callback: [Function] }

此外,如果我进行简单的开始/结束日期比较,我通常获得0作为从结尾减去开头的结果。

var start = Date.now();
var timer = setTimeout(function(){ console.log(timer, Date.now() - start );}, 0);

{ repeat: 0, callback: [Function] } 0

这些测试是使用Node.js 0.5.2完成的。

答案 2 :(得分:1)

应该注意,定时器的实现会因操作系统而异。例如,我记得一个“好老”的JTimer问题,其中计时器的分辨率在Windows上是16ms,在其他平台上是〜1ms。几乎可以肯定,在您的特定服务器上进行测试。