How do browsers pause/change Javascript when tab or window is not active?
Asked Answered
I

3

194

Background: I'm doing some user interface tests that need to detect if people are paying attention or not. But, this question is not about the page visibility 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:

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 window is 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)?
Ichthyo answered 8/4, 2013 at 5:36 Comment(9)
If they are paused, sites like Facebook wouldn't receive any chat messages on background tabs.Outhaul
+1 This doesn't happen anywhere, it wouldn't surprise me if (some) browsers lessoned the priority of setInterval, but I doubt it would make much difference.Beeman
Yeah there's no pausing, but I do remember reading that the setInterval/setTimeout times under 1000ms are changed to 1000ms when the tab/window is blurredTokoloshe
@Tokoloshe can you find a reliable source for that?Ichthyo
@AndrewMao I wish I could. Haha I'm sorry, I think it's just a browser implementation...it's definitely not part of any standard.Tokoloshe
@lan setInterval/setTimeout times under 1000ms are changed to 1000ms when the tab/window is blurred. Not clear what you tried to conveyDilative
+1 Great question. It would be good to see a side by side comparison of browser behaviours, as I believe the clamping behaviour when tabs are not active is not part of any standard.Enfranchise
i would suspect each browser does it different. onky way to find out is to check sources and or ask on the forums for every browser. Also, there's a chance this behavior changes a bit depending on the browser version.Cooper
i can only get about 200 executions per second on defered when the tab is active, 1 per sec on inactiveUngava
N
218

Test One

I have written a test specifically for this purpose:
Frame Rate Distribution: setInterval vs requestAnimationFrame

Note: This test is quite CPU intensive. requestAnimationFrame is not supported by IE 9- and 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.

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.

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.

// Provides control over the minimum timer interval for background tabs.
const double kBackgroundTabTimerInterval = 1.0;

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.

// 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

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.

Edge
Starting from Edge 14, setInterval is capped at 1000ms in inactive tabs. requestAnimationFrame is always paused in inactive tabs.

Safari
Just like Chrome, Safari caps setInterval at 1000ms when the tab is inactive. requestAnimationFrame is paused as well.

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.

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
Nebulosity answered 16/4, 2013 at 9:56 Comment(6)
Great answer. Any other possible known differences for functions other than setInterval and requestAnimationFrame?Ichthyo
@AndrewMao Not that I am aware of. I came across this issue when I was working on a library to reliably detect if JS reenabled with setInterval and requestAnimationFrame. The thing I know about is that setTimeout behaves similarly to setInterval, in that they both have the same minimum background interval in Firefox and Chrome, and no apparent limit in other browsers.Nebulosity
The Firefox setInterval minimum value can apparently be changed by opening the url about:config in the browser and changing the dom.min_background_timeout_value value to something else than 1000.Fire
can i use this to reload page every 5 seconds when browser is minimized ?, here is my question.Lorie
Note that chrome does not pause/reduce the rate at which requestAnimationFrame is called if the user simply switches application (Alt+Tab out of Chrome). As long as the tab is active in Chrome the "frame rate" is more or less constant.Janot
@JonasBerlin awesome! This has an immediate effect without browser restart.Rattlebox
S
12

What I observed : on inactive tabs in Chrome, all your setTimeout (must be the same for setInterval) waiting less than 1000ms are rounded to 1000ms. I think longer timeouts are not modified.

Seems to be the behavior since Chrome 11 and 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).

Shannashannah answered 10/4, 2013 at 8:36 Comment(3)
jQuery's focus and blur events seem to detect both tab and window switches, so it could conceivably work both ways. But I wonder how the window detects if it's actually visible or not.Ichthyo
Actually it has no connection with jQuery or Javascript as it is internal browser implementation.Shannashannah
Can you confirm this now in late 2016?Chante
A
1

A newer answer to complement these: on chrome 78.0.3904.108 I notice all of 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." Try running the following and switching to another tab!

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>
Ayannaaycock answered 11/12, 2019 at 23:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.