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

Tim*_*ers 0 javascript timer

我正在开发一个严重依赖计时器的项目。我见过 1-2 个场景,其中计时器速度减慢,并且没有按应有的那样每秒滴答一次,但 1 秒/滴答需要 2-3 秒。通常这是由于整个计算机速度变慢并且变得非常滞后。我无法复制它,但一些用户报告了类似的发现,一旦他们重置计算机,一切都会正常。

我的问题是,超时/间隔如何工作?如果浏览器陷入困境,它会减慢计时器的速度,还是基于 CPU/系统时间?另外,是否还有其他人发生过类似的情况,如果是这样,我可以采取哪些措施来纠正这种情况(即使系统很慢,也让 15 秒计时器在 15 秒后实际触发一个事件)?

Nie*_*sol 5

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

然而,即使setTimeout完全准确,处理其中的 JavaScript 也需要时间。尽管我们希望如此,但代码并不是真正实时的。这意味着,即使使用完全准确的 1,000 毫秒计时器,经过几千次迭代后,您也会开始注意到明显的差异。

总而言之,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);
Run Code Online (Sandbox Code Playgroud)

requestAnimationFrame功能使这变得更加容易。但是,请记住,这是一项新功能,大多数浏览器在没有供应商前缀的情况下都不会采用它。Internet Explorer 是我所知道的唯一具有此功能的浏览器。人们还说 IE 很糟糕!

不管怎样,假设你有一个合适的polyfill,它看起来像这样:

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);
});
Run Code Online (Sandbox Code Playgroud)

似乎需要做很多工作才能完成基本上只是美化的事情setTimeout,对吧?

嗯,是。但我特别喜欢的一件事是,它将requestAnimationFrame等到帧实际渲染完毕。特别是,这意味着如果您正在查看不同的选项卡,requestAnimationFrame它将等待您返回。我用它来延迟自动更新 AJAX 请求,允许用户实际看到更新,而不是回来对自己说“现在......更新了吗?我不知道,我不知道”记得以前是什么......”相反,他们会欣赏一些简洁的过渡,并告诉你它在更新之前等待你回来是多么酷;)当你的用户认为某件事很酷时,那就是了真的很酷。(专业提示:轮播并不酷 - 我知道很多人都可以很好地学习这一点!)

无论如何,我有点漫无目的。我不知道我是否回答了你的问题,但我当然希望我能启发你一些,并且你会发现这很有趣,尽管有些离题。

玩得开心!

  • 实际上,Firefox 和 Chrome 都没有前缀“requestAnimationFrame”。Firefox 自版本 23 起,Chrome 自版本 24 起,Safari 自版本 7 起,Opera 自版本 15 起。 (3认同)