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

标签 javascript timer

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

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

最佳答案

默认情况下,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);

使用新的 requestAnimationFrame 函数,这变得更加容易。但是,请记住,这是一项新功能,大多数浏览器在没有 vendor 前缀的情况下都不会采用它。 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);
});

对于基本上只是一个美化的 setTimeout 的东西来说,似乎需要做很多工作,对吧?

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

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

玩得开心!

关于javascript - 超时/间隔是基于 CPU 还是浏览器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19548679/

相关文章:

javascript - promise 完成后导出

Javascript 函数并返回 JSON

c - 计时器和系统日志组合将导致我的代码挂起

c# - 为什么这个方法会导致Code Analysis error CA2000 : Call Dispose()

c# - 计时器和按钮问题

javascript - 如何在 javascript 或 jquery 中渲染 json 对象的内部数组

javascript - 为什么从数组调用时会出现非法调用?

javascript - JS 定时器手动设置时间

Javascript 倒计时器 - 未按预期工作

javascript - Bootstrap JS 模态和菜单切换争议