Comment les navigateurs mettent-ils en pause/modifient-ils Javascript lorsque l'onglet ou la fenêtre n'est pas actif?
Contexte: je fais des tests d'interface utilisateur qui doivent détecter si les gens font attention ou non. Mais, cette question Est Pas à propos de L'API de visibilité de page .
Plus précisément, j'aimerais savoir comment mon code Javascript sera affecté si l'onglet actuel n'est pas actif, ou si la fenêtre du navigateur n'est pas active, dans différents navigateurs. J'ai déterré ce qui suit jusqu'à présent:
- ios 5 met en pause javascript lorsque tab n'est pas actif
-
setIntervaletsetTimeoutle délai est réduit lorsque les onglets ne sont pas actifs - on dirait que cela vient de commencer à apparaître récemment et peut gâcher les tests unitaires de Jasmine, autour d'autres choses. -
requestAnimationFrameest ralenti lorsque tab n'est pas actif (raisonnable, ne peut pas penser à pourquoi cela affecterait trop quelqu'un)
J'ai les questions suivantes:
- autres que les navigateurs mobiles, les navigateurs de bureau interrompent-ils l'exécution JS lorsqu'un onglet n'est pas actif? Quand et quels navigateurs?
- quels navigateurs réduisent la répétition de
setInterval? Est-il simplement réduit à une limite ou à un pourcentage? Par exemple, si j'ai une répétition de 10ms par rapport à une répétition de 5000ms, comment chacun sera-t-il affecté? - ces changements se produisent-ils si la fenêtre {[33] } est floue, par opposition à l'onglet? (J'imagine que ce serait plus difficile à détecter, car cela nécessite L'API du système d'exploitation.)
- , y a d'autres effets qui ne seraient pas observés dans un onglet actif? Pourraient-ils gâcher les choses serait-il exécuté correctement (c'est-à-dire les tests Jasmin susmentionnés)?
2 réponses
Test Un
J'ai écrit un test spécifiquement à cette fin:
Distribution de fréquence D'images: setInterval vs requestAnimationFrame
Remarque: Ce test est assez gourmand en CPU. requestAnimationFrame N'est pas pris en charge par IE 9 - et Opera 12-.
Le test enregistre le temps réel qu'il faut pour qu'un setInterval et requestAnimationFrame s'exécute dans différents navigateurs, et vous donne les résultats sous la forme d'une distribution. Vous pouvez modifier le nombre de millisecondes pour setInterval pour voir comment il fonctionne sous différents réglages. setTimeout fonctionne de la même manière qu'un setInterval en ce qui concerne les retards. {[3] } généralement par défaut à la 60fps en fonction du navigateur. Pour voir ce qui se passe lorsque vous passez à un onglet différent ou que vous avez une fenêtre inactive, ouvrez simplement la page, passez à un onglet différent et attendez un moment. Il continuera à enregistrer le temps réel qu'il faut pour ces fonctions dans un onglet inactif.
Deux
Une autre façon de le tester est de consigner l'horodatage à plusieurs reprises avec setInterval et requestAnimationFrame et affichez-le dans une console détachée. Vous pouvez voir à quelle fréquence il est mis à jour (ou s'il est jamais mis à jour) lorsque vous rendez l'onglet ou la fenêtre inactif.
Résultats
Chrome
Chrome limite l'intervalle minimum de setInterval à environ 1000 ms lorsque l'onglet est inactif. Si l'intervalle est supérieur à 1000 ms, il s'exécutera à l'intervalle spécifié. Il n'a pas d'importance si la fenêtre est floue, l'intervalle est limité uniquement lorsque vous passez à un onglet différent. requestAnimationFrame est mis en pause lorsque l'onglet est inactif.
// Provides control over the minimum timer interval for background tabs.
const double kBackgroundTabTimerInterval = 1.0;
https://codereview.chromium.org/6546021/patch/1001/2001
Firefox
Similaire à Chrome, Firefox limite l'intervalle minimum de setInterval à environ 1000 ms lorsque l'onglet (pas la fenêtre) est inactif. Cependant, requestAnimationFrame s'exécute exponentiellement plus lentement lorsque l'onglet est inactif, chaque image prenant 1s, 2s, 4s, 8s et ainsi de suite.
// 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 ne limite pas le délai dans setInterval lorsque l'onglet est inactif, mais il met en pause requestAnimationFrame dans les onglets inactifs. Peu importe si la fenêtre est floue ou non.
Bord
À partir du bord 14, setInterval est plafonné à 1000 ms dans les onglets inactifs. requestAnimationFrame est toujours en pause dans les onglets inactifs.
Safari
Tout comme Chrome, Safari caps setInterval à 1000ms lorsque l'onglet est inactif. {[3] } est également en pause.
Opéra
Depuis L'adoption du moteur Webkit, Opera présente le même comportement que Chrome. setInterval est plafonné à 1000ms et requestAnimationFrame est mis en pause lorsque l'onglet est inactif.
Résumé
Répétition des intervalles pour les onglets inactifs:
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
Ce que j'ai observé : sur les onglets inactifs dans Chrome, toutes vos setTimeout (doit être le même pour setInterval) en attente de moins de 1000ms sont arrondis à 1000ms. Je pense que les délais d'attente plus longs ne sont pas modifiés.
Semble être le comportement depuis Chrome 11 et Firefox 5.0 : https://developer.mozilla.org/en-US/docs/DOM/window.setTimeout#Inactive_tabs
De plus, Je ne pense pas qu'il se comporte de cette façon lorsque toute la fenêtre est inactive (mais semble assez facile à étudier).