javascript 浏览器如何暂停/更改JavaScript时选项卡或窗口未激活?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15871942/
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
How do browsers pause/change Javascript when tab or window is not active?
提问by Andrew Mao
Background: I'm doing some user interface tests that need to detect if people are paying attention or not. But, this question is notabout the page visibility API.
背景:我正在做一些用户界面测试,需要检测人们是否在关注。但是,这个问题是不是有关的页面知名度API。
Specifically, I would like to know how my Javascript code will be affected if the current tab is not active, or the browser window is not active, in different browsers. I've dug up the following so far:
具体来说,我想知道如果当前选项卡在不同浏览器中未处于活动状态或浏览器窗口未处于活动状态,我的 Javascript 代码将如何受到影响。到目前为止,我已经挖掘了以下内容:
- ios 5 pauses javascript when tab is not active
setInterval
andsetTimeout
delay is reduced when tabs are not active- seems like this just started appearing recently and can mess up Jasmine unit tests, around other things.requestAnimationFrame
is slowed when tab is not active (reasonable, can't think of why this would affect anyone too much)
- 当Tab未激活时,iOS 5暂停JavaScript
setInterval
setTimeout
当标签不活动时,延迟减少- 似乎这刚刚开始最近出现,并且可以在其他事情上弄乱茉莉单位测试。requestAnimationFrame
当标签未激活时(合理,无法想一想为什么会影响任何人)
I have the following questions:
我有以下问题:
- Other than mobile browsers, do desktop browsers ever pause JS execution when a tab is not active? When and which browsers?
- Which browsers reduce the
setInterval
repeat? Is it just reduced to a limit or by a percentage? For example, if I have a 10ms repeat versus a 5000ms repeat, how will each be affected? - Do these changes happen if the windowis out of focus, as opposed to just the tab? (I imagine it would be harder to detect, as it requires the OS API.)
- Are there any other effects that would not be observed in an active tab? Could they mess things up that would otherwise execute correctly (i.e. the aforementioned Jasmine tests)?
- 除了移动浏览器,桌面浏览器是否会在选项卡不活动时暂停 JS 执行?何时使用哪些浏览器?
- 哪些浏览器减少了
setInterval
重复?它只是减少到一个限制还是一个百分比?例如,如果我有 10 毫秒的重复和 5000 毫秒的重复,那么每个重复会受到什么影响? - 如果窗口失焦,而不仅仅是选项卡,是否会发生这些变化?(我想它会更难检测,因为它需要 OS API。)
- 在活动选项卡中是否有任何其他效果不会被观察到?他们会不会把本来可以正确执行的事情搞砸(即前面提到的 Jasmine 测试)?
回答by Antony
Test One
测试一
I have written a test specifically for this purpose:
Frame Rate Distribution: setInterval vs requestAnimationFrame
我为此专门编写了一个测试:
帧速率分布:setInterval vs requestAnimationFrame
Note: This test is quite CPU intensive. requestAnimationFrame
is not supported by IE 9- and Opera 12-.
注意:此测试非常占用 CPU。requestAnimationFrame
IE 9- 和 Opera 12- 不支持。
The test logs the actual time it takes for a setInterval
and requestAnimationFrame
to run in different browsers, and gives you the results in the form of a distribution. You can change the number of milliseconds for setInterval
to see how it runs under different settings. setTimeout
works similarly to a setInterval
with respect to delays. requestAnimationFrame
generally defaults to the 60fps depending on the browser. To see what happens when you switch to a different tab or have an inactive window, simply open the page, switch to a different tab and wait for a while. It will continue to log the actual time it takes for these functions in an inactive tab.
该测试记录 asetInterval
和requestAnimationFrame
在不同浏览器中运行所需的实际时间,并以分布的形式为您提供结果。您可以更改毫秒数setInterval
以查看它在不同设置下的运行情况。对于延迟setTimeout
,其工作方式与 a 类似setInterval
。requestAnimationFrame
通常默认为 60fps,具体取决于浏览器。要查看切换到其他选项卡或使用非活动窗口时会发生什么,只需打开页面,切换到其他选项卡并等待一段时间。它将继续在非活动选项卡中记录这些功能所需的实际时间。
Test Two
测试二
Another way to test it is to log the timestamp repeatedly with setInterval
and requestAnimationFrame
and view it in a detached console. You can see how frequently it is updated (or if it is ever updated) when you make the tab or window inactive.
另一种测试它的方法是使用setInterval
和重复记录时间戳requestAnimationFrame
并在分离的控制台中查看它。当您使选项卡或窗口处于非活动状态时,您可以看到它的更新频率(或是否曾经更新过)。
Results
结果
Chrome
Chrome limits the minimum interval of setInterval
to around 1000ms when the tab is inactive. If the interval is higher than 1000ms, it will run at the specified interval. It does not matter if the window is out of focus, the interval is limited only when you switch to a different tab. requestAnimationFrame
is paused when the tab is inactive.
Chrome
ChromesetInterval
将选项卡处于非活动状态时限制为大约1000ms的最小间隔。如果间隔大于 1000ms,它将以指定的间隔运行。窗口是否失焦并不重要,只有当您切换到不同的选项卡时,间隔才会受到限制。requestAnimationFrame
选项卡处于非活动状态时暂停。
// Provides control over the minimum timer interval for background tabs.
const double kBackgroundTabTimerInterval = 1.0;
https://codereview.chromium.org/6546021/patch/1001/2001
https://codereview.chromium.org/6546021/patch/1001/2001
Firefox
Similar to Chrome, Firefox limits the minimum interval of setInterval
to around 1000ms when the tab (not the window) is inactive. However, requestAnimationFrame
runs exponentially slower when the tab is inactive, with each frame taking 1s, 2s, 4s, 8s and so on.
Firefox
类似于Chrome,FirefoxsetInterval
将标签(不是窗口)处于非活动状态时将最小间隔限制为大约1000ms。However, requestAnimationFrame
runs exponentially slower when the tab is inactive, with each frame taking 1s, 2s, 4s, 8s and so on.
// The default shortest interval/timeout we permit
#define DEFAULT_MIN_TIMEOUT_VALUE 4 // 4ms
#define DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE 1000 // 1000ms
https://hg.mozilla.org/releases/mozilla-release/file/0bf1cadfb004/dom/base/nsGlobalWindow.cpp#l296
https://hg.mozilla.org/releases/mozilla-release/file/0bf1cadfb004/dom/base/nsGlobalWindow.cpp#l296
Internet Explorer
IE does not limit the delay in setInterval
when the tab is inactive, but it pauses requestAnimationFrame
in inactive tabs. It does not matter whether the window is out of focus or not.
Internet Explorer
IE 不会限制setInterval
选项卡处于非活动状态时的延迟,但会requestAnimationFrame
在非活动选项卡中暂停。窗口是否失焦并不重要。
Edge
Starting from Edge 14, setInterval
is capped at 1000ms in inactive tabs. requestAnimationFrame
is always paused in inactive tabs.
Edge
从 Edge 14 开始,setInterval
在非活动选项卡中的上限为 1000 毫秒。requestAnimationFrame
在非活动选项卡中始终暂停。
Safari
Just like Chrome, Safari caps setInterval
at 1000ms when the tab is inactive. requestAnimationFrame
is paused as well.
Safari
就像Chrome,setInterval
当标签处于非活动状态时,Safari Caps在100毫秒时。requestAnimationFrame
也暂停了。
Opera
Since the adoption of the Webkit engine, Opera exhibits the same behavior as Chrome. setInterval
is capped at 1000ms and requestAnimationFrame
is paused when the tab is inactive.
Opera
自采用 Webkit 引擎以来,Opera 表现出与 Chrome 相同的行为。setInterval
上限为 1000 毫秒,并requestAnimationFrame
在选项卡处于非活动状态时暂停。
Summary
概括
Repeating intervals for inactive tabs:
非活动选项卡的重复间隔:
setInterval requestAnimationFrame Chrome 9- not affected not supported 10 not affected paused 11+ >=1000ms paused Firefox 3- not affected not supported 4 not affected 1s 5+ >=1000ms 2ns (n = number of frames since inactivity) IE 9- not affected not supported 10+ not affected paused Edge 13- not affected paused 14+ >=1000ms paused Safari 5- not affected not supported 6 not affected paused 7+ >=1000ms paused Opera 12- not affected not supported 15+ >=1000ms paused
回答by Andrew Mao
What I observed : on inactive tabs in Chrome, all your setTimeout
(must be the same for setInterval
) waiting less than 1000msare rounded to 1000ms. I think longer timeouts are not modified.
我观察到:在Chrome 中的非活动选项卡上,所有等待时间小于1000 毫秒的setTimeout
(必须相同setInterval
)四舍五入为1000 毫秒。我认为不会修改更长的超时时间。
Seems to be the behavior since Chrome 11and Firefox 5.0: https://developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs
似乎是自Chrome 11和Firefox 5.0以来的行为:https: //developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs
Furthermore, I don't think it behaves this way when the whole window is inactive (but it seems quite easy to investigate).
此外,我不认为当整个窗口处于非活动状态时它的行为方式(但似乎很容易调查)。
回答by Gershom
A newer answer to complement these: on chrome 78.0.3904.108 I notice allof these timeouts (not just those below 1000ms) taking a bit longer than expected when I move to a different tab, and then come back. The behaviour I am seeing is more correctly described as "All timeouts on inactive tabs may be delayed by some additional amount, to a maximum of 1000ms.":
一个更新的答案来补充这些:在 chrome 78.0.3904.108 上,当我移动到不同的选项卡时,我注意到所有这些超时(不仅仅是那些低于 1000 毫秒的超时)花费的时间比预期的要长一些,然后又回来了。我看到的行为更准确地描述为“非活动选项卡上的所有超时可能会延迟一些额外的时间,最多为 1000 毫秒。” :
let timeouts = [ 500, 1000, 2000, 3000, 10000 ];
let minExcess = document.getElementsByClassName('minExcess')[0];
timeouts.forEach(ms => {
let elem = document.getElementsByClassName(`t${ms}`)[0];
let cnt = 0;
let lastMs = +new Date();
let f = () => {
let curMs = +new Date();
let disp = document.createElement('p');
let net = curMs - lastMs;
lastMs = curMs;
setTimeout(f, ms);
if (minExcess.value && (net - ms) < parseInt(minExcess.value)) return;
disp.innerText = `${net},`;
elem.appendChild(disp);
if (++cnt > 10) elem.firstElementChild.remove();
};
setTimeout(f, ms);
});
body { font-size: 80%; }
div {
max-height: 80px;
overflow-x: auto;
background-color: rgba(0, 0, 0, 0.1);
margin-bottom: 2px;
white-space: nowrap;
}
p { margin: 0; }
div > p {
margin: 0;
display: inline-block;
vertical-align: top;
margin-right: 2px;
}
input { margin: 0 0 10px 0; }
.t500:before { display: block; content: '500ms'; font-weight: bold; }
.t1000:before { display: block; content: '1000ms'; font-weight: bold; }
.t2000:before { display: block; content: '2000ms'; font-weight: bold; }
.t3000:before { display: block; content: '3000ms'; font-weight: bold; }
.t10000:before { display: block; content: '10000ms'; font-weight: bold; }
<p>Ignore any values delayed by less than this amount:</p>
<input type="text" class="minExcess" value="200" pattern="^[0-9]*$"/>
<div class="timeout t500"></div>
<div class="timeout t1000"></div>
<div class="timeout t2000"></div>
<div class="timeout t3000"></div>
<div class="timeout t10000"></div>