超时/间隔是基于CPU还是基于浏览器?

时间:2013-10-23 17:40:51

标签: javascript timer

我正在开发一个严重依赖计时器的项目。我已经看过1-2个场景,其中计时器减速并且没有按每秒钟滴答,但是1秒/滴答需要2-3秒。通常是由于整台计算机变慢而变得非常迟缓。我无法复制它,但有些用户报告了类似的结果,一旦他们重置计算机,一切都是应有的。

我的问题是,超时/间隔如何工作?如果浏览器陷入困境,是否会降低计时器的速度,还是基于CPU /系统时间?此外,还有其他人有类似的事情发生,如果是这样,我可以采取什么类型的事情来纠正这种情况(即使系统运行缓慢,15秒计时器实际上会在15秒后触发事件)?

2 个答案:

答案 0 :(得分:4)

默认情况下,setTimeout使用系统的内部计时器,其粒度为16.66 ... ms(频率为60 Hz,即每秒60帧)。有些浏览器会覆盖它(这对处理器来说实际上是非常糟糕的 - 尽管在Internet Explorer的情况下,如果计算机专门设置为“高性能”模式,它只会这样做,否则它会使用危害较小的60fps限制)

但是,即使setTimeout完全准确,也需要时间来处理JavaScript。尽管我们喜欢它,代码并不是真正的实时。这意味着,即使使用精确准确的1,000ms计时器,经过几千次迭代,您也会开始注意到明显的差异。

总而言之,setTimeout(以及setInterval扩展名setTimeout,基本上只是var start = new Date().getTime(); setInterval(function() { var now = new Date().getTime(), delta = now-start; console.log("Timer fired after "+delta+"ms"); // chances are, you'll see numbers between 984 and 1016, unless your browser // is a processor-killing, rainforest-destroying monster :p // even then, you'll probably see some 999s and 1001s, depending on how // busy your computer is with other tasks. Open a YouTube video, you'll see. },1000); 并且自动续订)是不可靠的。如果您需要可靠性,则必须使用增量计时。

Delta时间是指您保存启动计时器的时间,并将其与计时器触发的时间进行比较。一个简单的例子就是:

requestAnimationFrame

使用新的var previous = new Date().getTime(); // or Date.now() if you're feeling brave... // or are already excluding old browsers via canvas use requestAnimationFrame(function(now) { var loopit = arguments.callee, delta = now-previous; previous = now; console.log(delta); // should be around 16 or 17 requestAnimationFrame(loopit); }); 功能,这变得更加容易。但是,请记住,这是一项新功能,并且大多数浏览器在没有供应商前缀的情况下都没有采用它。 Internet Explorer是我唯一知道的浏览器。人们说IE糟透了!

无论如何,假设你有一个合适的polyfill,它看起来像这样:

setTimeout

对于基本上只是美化requestAnimationFrame的东西来说,似乎有很多工作,对吗?

嗯,是的。但我特别喜欢的一点是requestAnimationFrame将等到实际渲染帧。特别是,这意味着如果您正在查看其他标签,{{1}}将等待您回来。我使用它来延迟自动更新AJAX请求,允许用户实际看到更新然后在那里,而不是回来并对自己说“现在......有更新吗?我不知道,我不知道记住它之前是什么......“相反,他们会欣赏一些简洁的过渡,然后告诉你在更新之前它等待你回来是多么酷;)当你的用户认为某些东西很酷时,那就是真的很酷。 (Protip:旋转木马并不酷 - 我知道很多人会很好地学习这个!)

无论如何,我有点絮絮叨叨。我不知道我是否回答了你的问题,但我当然希望我已经开悟了一些,并且你发现这很有趣,如果切线的话。

玩得开心!

答案 1 :(得分:1)

以下是setTimeout上的有用链接。 (由John Resig撰写)

总结文章:

  • JavaScript引擎只有一个线程,迫使异步事件排队等待执行。
  • setTimeout和setInterval在执行异步代码方面有根本的不同。
  • 如果计时器被阻止立即执行,它将被延迟到下一个可能的执行点(这将超过所需的延迟)。
  • 如果间隔时间足够长(超过指定的延迟),间隔可以无延迟地执行。