2011-08-28 138 views
34

在浏览器中,如果使用setTimeout从由setTimeout调用的函数内,则4毫秒的最小延迟将被强制执行。 Mozilla的开发者wiki describes this behaviour,并提到它有become standardized in HTML5Node.js对setTimeout执行最小延迟吗?

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

不Node.js的强制执行的setTimeout的最小延迟,如网页浏览器吗?

回答

17

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

节点使用libuv这对于低级别系统之类的东西文件系统,联网的东西等。一种的那些东西跨平台抽象层是定时器,节点周围提供了一个最小的包装。在libuv级别,所用的定时器是系统特定的高精度定时器。例如,在Windows中,这是通过使用QueryPerformanceFrequencyFileTimeToSystemTime来实现的,它提供了以纳秒为单位测量的分辨率。

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

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

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

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

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

15

从这个测试,它似乎并不认为它确实有一个最小延迟。

如果你这样做有一个10ms持续时间长的返回值到控制台setTimeout(),这是你会得到什么:

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完成。

1

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