Javascript Chrome:超时/间隔在后台选项卡中暂停?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6032429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:57:34  来源:igfitidea点击:

Chrome: timeouts/interval suspended in background tabs?

javascriptgoogle-chrometabssettimeout

提问by KooiInc

I was testing the accuracy of setTimeoutusing this test. Now I noticed that (as expected) setTimeoutis not very accurate but for most appliances not dramatically inaccurate. Now if I run the test in in Chrome and let it run in a background tab (so, switching to another tab and browse on there), returning to the test and inspecting te results (if the test finished) they are dramatically changed. It looks like the timeouts have been running a lot slower. Tested in FF4 or IE9 this didn't occur.

我正在测试setTimeout使用测试的准确性。现在我注意到(正如预期的那样)setTimeout不是很准确,但对于大多数设备来说并不是非常不准确。现在,如果我在 Chrome 中运行测试并让它在后台选项卡中运行(因此,切换到另一个选项卡并在那里浏览),返回测试并检查结果(如果测试完成),它们会发生巨大变化。看起来超时的运行速度要慢得多。在 FF4 或 IE9 中测试没有发生这种情况。

So it looks like Chrome suspends or at least slows down javascript execution in a tab that has no focus. Couldn't find much on the net on the subject. It would mean that we can't run background tasks, like for example checking periodically on a server using XHR calls and setInterval(I suspect to see the same behavior for setInterval, will write a test if time is with me).

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

Has anyone encountered this? Would there be there a workaround for this suspension/slowing down? Would you call it a bug and should I file it as such?

有没有人遇到过这个?这种暂停/减速是否有解决方法?你会称它为错误吗,我应该这样归档吗?

采纳答案by pimvdb

I recently asked about this and it is behaviour by design. When a tab is inactive, only at a maximum of once per second the function is called. Here is the code change.

我最近问过这个问题,这是设计行为。When a tab is inactive, only at a maximum of once per second the function is called. 这是代码更改

Perhaps this will help: How can I make setInterval also work when a tab is inactive in Chrome?

也许这会有所帮助: 当 Chrome 中的选项卡处于非活动状态时,如何使 setInterval 也能工作?

TL;DR:use Web Workers.

TL;DR:使用Web Workers

回答by Ruslan Tushov

There is a solution to use Web Workers, because they run in separate process and are not slowed down

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

I've written a tiny script that can be used without changes to your code - it simply overrides functions setTimeout, clearTimeout, setInterval, clearInterval

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

Just include it before all your code

只需在所有代码之前包含它

http://github.com/turuslan/HackTimer

http://github.com/turuslan/HackTimer

回答by Kaan Soral

Playing an ~empty sound forces the browser to retain the performance - I discovered it after reading this comment: How to make JavaScript run at normal speed in Chrome even when tab is not active?

播放 ~empty 声音会强制浏览器保持性能 - 我在阅读此评论后发现了这一点:即使选项卡未处于活动状态,如何使 JavaScript 在 Chrome 中以正常速度运行?

I need unlimited performance on-demand for a browser game that uses WebSockets, so I know from experience that using WebSockets doesn't ensure unlimited performance, but from tests, playing an audio file seems to ensure it

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

Here's 2 empty audio loops I created for this purpose, you can use them freely, commercially: http://adventure.land/sounds/loops/empty_loop_for_js_performance.ogghttp://adventure.land/sounds/loops/empty_loop_for_js_performance.wav

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

(They include -58db noise, -60db doesn't work)

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

I play them, on user-demand, with Howler.js: https://github.com/goldfire/howler.js

我根据用户需求使用 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,
    });
}

It's sad that there is no built-in method to turn full javascript performance on/off by default, yet, crypto miners can hiHyman all your computing threads using Web Workers without any prompt :|

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

回答by gorkemcnr

I have released worker-intervalnpm package which setInterval and clearInterval implementation with using Web-Workers to keep up and running on inactive tabs for Chrome, Firefox and IE.

我已经发布了worker-intervalnpm 包,它使用 Web-Workers 在 Chrome、Firefox 和 IE 的非活动选项卡上保持和运行 setInterval 和 clearInterval 实现。

Most of the modern browsers (Chrome, Firefox and IE), intervals (window timers) are clamped to fire no more often than once per second in inactive tabs.

大多数现代浏览器(Chrome、Firefox 和 IE)、时间间隔(窗口计时器)都被限制为在非活动选项卡中每秒触发一次。

You can find more information on

你可以找到更多信息

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Timeouts_and_intervals

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Timeouts_and_intervals

回答by Carey Estes

I updated my jQuery core to 1.9.1, and it solved the Interval discrepancy in inactive tabs. I would try that first, then look into other code override options.

我将我的 jQuery 核心更新到 1.9.1,它解决了非活动选项卡中的间隔差异。我会先尝试一下,然后再研究其他代码覆盖选项。

回答by SwiftNinjaPro

here is my solution which gets the current millisecond, and compares it to the millisecond that the function was created. for interval, it will update the millisecond when it runs the function. you can also grab the interval/timeout by an id.

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