2010-10-06 77 views
4

是否有无论如何在浏览器中创建一个变速计时器,它将给所有操作系统和浏览器提供完全相同的结果?如果我想每个用户每分钟140次跳动,无论他们的电脑速度如何。基于Web的计时器

我一直在使用javascript setTimeout()和setInterval(),但我认为它们依赖于计算机的速度和程序中的代码量。 如何将系统时钟并入浏览器?还是其他想法?

+0

你有任何引用或测试来支持_setTimeout_不准确的说法吗?它总是为我工作(虽然我没有验证它到每毫秒)。 – 2010-10-06 02:06:21

回答

6

你必须在你的解决方案中使用setTimeoutsetInterval,但是这将是不准确的,原因如下:

  1. 浏览器都有一个最小超时,这不是0毫秒。跨浏览器的最小值约为14毫秒。
  2. 定时器不精确。它们代表排队时间,而不是执行时间。如果在你的定时器触发时别的东西正在执行,你的代码会被推到一个队列中等待,并且可能直到很晚才会真正执行。

您可能打算使用setTimeout以及手动跟踪当前时间(使用Date)来执行您的程序。对于你来说,尝试这样的事情:

function someAction(delta) { 
    // ... 
} 

function beat() { 
    var currentTime = +new Date; 
    var delta = currentTime - pastTime; 

    if (delta > 430) { // 430ms ~ 140bpm 
    pastTime = currentTime; 
    someAction(); 
    } 

    setTimeout(beat, 107); // 4x resolution 
} 

var pastTime = +new Date; 
beat(); 

这应该接近每分钟140次,使用更高的分辨率,以避免更大的延迟。尽管这只是一个示例,但您可能需要更多地努力才能使其在应用程序中以最佳方式运行。

+0

(来自@gravityboy) 谢谢本,这是一个很好的答案。如果它超过阈值数,它会执行一个超时4次然后beat()只会调用someaction(),是正确的?如果它在430的阈值之前被称为几毫秒,会发生什么?那么在再次等待107次超时之前,它不会再有机会开火? 您认为setTimeout中可以使用的最小数字是什么? – bcherry 2010-10-06 20:26:01

+0

(from @gravityboy继续) 另外你怎么看只是没有setimeout循环,只是使用... var currentTime = + new Date; var delta = currentTime - pastTime; 它会运行并检查计算机允许的速度。字面上数百次,然后在增量变差时调用该函数。 这是一个失控的循环? p.s.我认为= +新日期是一个错字,但不是。它以毫秒显示日期?我甚至无法在任何地方找到记录。 – bcherry 2010-10-06 20:26:36

+0

是的,你是正确的,这可能导致100ms的延迟。这只是应用程序响应和计时器准确性方面的折衷。如果你使用0ms设置'setTimeout',它将执行浏览器允许的最快速度(在某些情况下约14ms),这将提供最好的分辨率,从而达到最高的准确度。但是,这会以牺牲其他应用程序为代价。对于简单的事情来说,这应该很好,但对于复杂的应用程序来说,这可能效果不佳。 – bcherry 2010-10-06 20:28:51

0

你可以使用的最好的是setInterval()或尝试从Date()派生的东西。

请注意,时间并不准确,我认为是因为JavaScript的单线程本质。

0

setTimeout()setInterval()功能几乎是最好的你会得到。这些函数的超时参数以毫秒为单位指定,取决于运行浏览器的计算机的总体速度,其值为而不是

但是,这些函数当然不是硬实时函数,并且如果浏览器在您的超时或时间间隔到期时忙于执行其他操作,可能会稍微延迟,然后实际调用回调函数。