我正在开发一个严重依赖计时器的项目。我已经看过1-2个场景,其中计时器减速并且没有按每秒钟滴答,但是1秒/滴答需要2-3秒。通常是由于整台计算机变慢而变得非常迟缓。我无法复制它,但有些用户报告了类似的结果,一旦他们重置计算机,一切都是应有的。
我的问题是,超时/间隔如何工作?如果浏览器陷入困境,是否会降低计时器的速度,还是基于CPU /系统时间?此外,还有其他人有类似的事情发生,如果是这样,我可以采取什么类型的事情来纠正这种情况(即使系统运行缓慢,15秒计时器实际上会在15秒后触发事件)?
答案 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撰写)
总结文章: