Chrome:超时/间隔暂停在背景标签中?


130

我正在测试setTimeout使用测试的准确性。现在,我注意到(如预期的那样)setTimeout不是很准确,但是对于大多数设备而言,并不是十分不准确。现在,如果我在Chrome中运行测试并让其在后台标签中运行(因此,切换到另一个标签并在该标签上浏览),返回测试并检查结果(如果测试完成),它们将发生很大的变化。超时似乎一直慢很多。在FF4或IE9中进行了测试,但这没有发生。

因此,Chrome似乎在没有焦点的标签中暂停或至少减慢了javascript的执行速度。在网上找不到太多关于该主题的信息。这将意味着我们无法运行后台任务,例如,使用XHR调用定期检查服务器上的setIntervalsetInterval如果时间不多,我怀疑会看到的相同行为会编写测试)。

有人遇到过这个吗?暂停/放慢速度会有解决方法吗?您将其称为错误,还是应该这样提交?


有趣!重新访问标签后,您能否确定Chrome是否正在暂停并恢复计时器或重新启动计时器?还是行为随机?Chrome是否在独立的进程中运行标签页,这可能与它有关吗?
HyderA 2011年

@gAMBOOKa:看看@ pimvdb的答案。可能会减慢到每秒最多一次。
KooiInc

4年后,这个问题仍然存在。我为div设置了一个setTimeOut transition,因此并非所有div都同时转换,而是实际上彼此间隔15毫秒,从而产生了一些滚动效果。当我转到另一个选项卡并过一会儿再返回时,所有div同时转换,并且setTimeOut完全被忽略。对于我的项目来说,这不是什么大问题,但这是一个奇怪而又不必要的添加。
Rvervuur​​t 2015年

对于动画中按顺序调用setTimeout的动画,对我们而言,解决方案是确保我们记住计时器的句柄/ ID(它是从setTimeout返回的),并且在设置新计时器之前,如果已经设置了计时器,则首先调用clearTimeout得到了处理。在我们的例子中,这意味着当您返回到选项卡时,在播放动画方面可能会有一些最初的困惑,但它很快就会自动整理出来并恢复常规动画。我们本来以为这是最初没有代码的问题。
动作丹

Answers:



22

有一个使用Web Workers的解决方案,因为它们在单独的进程中运行并且不会减慢速度

我已经编写了一个很小的脚本,无需更改您的代码即可使用它-它只是覆盖函数setTimeout,clearTimeout,setInterval,clearInterval

只需在所有代码之前添加它

http://github.com/turuslan/HackTimer


7
很好,但是请注意:1.工人无法访问DOM,2.工人只有在自己保存在文件中时才会执行。在很多情况下,它不是 setTimeout的直接替代。
马达拉的幽灵

1
没错,但是某些现代浏览器允许使用Blob(html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers)使用没有自己文件的worker
Ruslan Tushov 2016年

1
即使这样,Web Workers仍缺少许多功能(即DOM),这些功能使它们可以安全地替代setTimeout和co。
马达拉的幽灵

对于必须在前端运行的代码,例如,我们想在做其他事情的同时完成繁重的图形处理任务呢?
迈克尔”于2009年

好了,您可以创建Workers,Service Workers并通过数据URL使用canvas API。new Worker('data:text/javascript,(' + function myWorkerCode () { /*...*/ } + '()')。这也是检查您是否已经导入表达支持的一个好方法:try { eval('import("data:text/javascript,void 0")') } catch (e) { /* no support! */ }
法比奥·桑托斯

9

播放〜空的声音会强制浏览器保持性能-阅读以下注释后,我发现了它:即使选项卡未激活,如何使JavaScript在Chrome中以正常速度运行?

对于使用WebSockets的浏览器游戏,我需要按需提供无限的性能,因此我从经验中知道使用WebSockets并不能确保无限的性能,但是从测试来看,播放音频文件似乎可以确保它的性能。

这是我为此创建的2个空音频循环,您可以在商业上免费使用它们:http : //adventure.land/sounds/loops/empty_loop_for_js_performance.ogg http://adventure.land/sounds/loops/empty_loop_for_js_performance.wav

(它们包括-58db噪声,-60db不起作用)

我根据需要使用Howler.js播放它们:https : //github.com/goldfire/howler.js

function performance_trick()
{
    if(sounds.empty) return sounds.empty.play();
    sounds.empty = new Howl({
        src: ['/sounds/loops/empty_loop_for_js_performance.ogg','/sounds/loops/empty_loop_for_js_performance.wav'],
        volume:0.5,
        autoplay: true, loop: true,
    });
}

令人遗憾的是,没有内置方法默认情况下可以打开/关闭完整的javascript性能,但是,加密矿工可以使用Web Workers劫持所有计算线程,而无需任何提示:|


谢谢,58db耳机非常好听,但静音站点可以解决该问题
Kaan Soral

1

我已经发布了worker-interval npm程序包,该程序包setInterval和clearInterval实现,使用Web-Workers来保持和运行Chrome,Firefox和IE的非活动选项卡。

大多数现代浏览器(Chrome,Firefox和IE)的时间间隔(窗口计时器)在不活动的标签页中的触发频率都不超过每秒一次。

您可以在以下找到更多信息

https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers#Timeouts_and_intervals


0

我将jQuery核心更新为1.9.1,并解决了非活动标签中的时间间隔差异。我会先尝试一下,然后再研究其他代码替代选项。


您从哪个版本升级?我
〜1.6

0

这是我的解决方案,它获取当前毫秒,并将其与创建函数的毫秒进行比较。对于间隔,它将在运行该函数时更新毫秒。您还可以通过ID获取间隔/超时。

<script>

var nowMillisTimeout = [];
var timeout = [];
var nowMillisInterval = [];
var interval = [];

function getCurrentMillis(){
    var d = new Date();
    var now = d.getHours()+""+d.getMinutes()+""+d.getSeconds()+""+d.getMilliseconds();
    return now;
}

function setAccurateTimeout(callbackfunction, millis, id=0){
    nowMillisTimeout[id] = getCurrentMillis();
    timeout[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisTimeout[id] + +millis)){callbackfunction.call(); clearInterval(timeout[id]);} }, 10);
}

function setAccurateInterval(callbackfunction, millis, id=0){
    nowMillisInterval[id] = getCurrentMillis();
    interval[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisInterval[id] + +millis)){callbackfunction.call(); nowMillisInterval[id] = getCurrentMillis();} }, 10);
}

//usage
setAccurateTimeout(function(){ console.log('test timeout'); }, 1000, 1);

setAccurateInterval(function(){ console.log('test interval'); }, 1000, 1);

</script>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.