web-dev-qa-db-fra.com

Comment les navigateurs mettent-ils en pause / modifient-ils Javascript quand l'onglet ou la fenêtre n'est pas actif?

Contexte: Je fais des tests d'interface utilisateur qui doivent détecter si des personnes sont attentives ou non. Mais, cette question concerne pas environ l'API de visibilité de la page .

Plus précisément, j'aimerais savoir comment mon code Javascript sera affecté si l'onglet en cours n'est pas actif ou si la fenêtre du navigateur n'est pas active dans différents navigateurs. J'ai déterré les éléments suivants jusqu'à présent:

J'ai les questions suivantes:

  • À part les navigateurs mobiles, les navigateurs de bureau suspendent-ils l'exécution de JS lorsqu'un onglet n'est pas actif? Quand et quels navigateurs?
  • Quels navigateurs réduisent la répétition de setInterval? Est-ce simplement réduit à une limite ou à un pourcentage? Par exemple, si j'ai une répétition de 10 ms par rapport à une répétition de 5000 ms, comment cela sera-t-il affecté?
  • Ces changements se produisent-ils si la fenêtre est floue, par opposition à l'onglet? (J'imagine qu'il serait plus difficile à détecter, car il nécessite l'API du système d'exploitation.)
  • Existe-t-il d'autres effets qui ne seraient pas observés dans un onglet actif? Pourraient-ils gâcher des choses qui autrement s'exécuteraient correctement (c'est-à-dire les tests Jasmine susmentionnés)?
154
Andrew Mao

Test One

J'ai écrit un test spécialement à cet effet:
Distribution de la fréquence d'images: setInterval vs requestAnimationFrame

Remarque: ce test nécessite beaucoup de ressources processeur. requestAnimationFrame n'est pas supporté par IE 9- et Opera 12-.).

Le test enregistre le temps réel nécessaire pour que 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 s'exécute sous différents paramètres. setTimeout fonctionne de la même manière qu'un setInterval en ce qui concerne les retards. requestAnimationFrame utilise généralement la valeur par défaut de 60 images par seconde en fonction du navigateur. Pour voir ce qui se passe lorsque vous passez à un autre onglet ou que vous avez une fenêtre inactive, ouvrez simplement la page, passez à un autre onglet et attendez un moment. Il continuera à enregistrer la durée réelle nécessaire à ces fonctions dans un onglet inactif.

Test deux

Une autre façon de le tester consiste à enregistrer l'horodatage à plusieurs reprises avec setInterval et requestAnimationFrame, puis à l'afficher dans une console séparée. Vous pouvez voir à quelle fréquence il est mis à jour (ou s'il l'est jamais) lorsque vous désactivez l'onglet ou la fenêtre.

Résultats

Chrome
Chrome limite l'intervalle minimal 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é. Peu importe que la fenêtre soit floue, l'intervalle n'est limité que lorsque vous passez à un autre onglet. requestAnimationFrame est suspendu 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
Semblable à Chrome, Firefox limite l’intervalle minimum de setInterval à environ 1000 ms lorsque l’onglet (et non la fenêtre) est inactif. Cependant, requestAnimationFrame s'exécute de manière exponentielle plus lente lorsque l'onglet est inactif, chaque image prenant 1, 2, 4, 8, etc.

// 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 des onglets inactifs. Peu importe que la fenêtre soit floue ou non.

Edge
Depuis Edge 14, setInterval est limité à 1000 ms dans les onglets inactifs. requestAnimationFrame est toujours en pause dans les onglets inactifs.

Safari
À l’instar de Chrome, Safari met setInterval à 1000 ms lorsque l’onglet est inactif. requestAnimationFrame est également en pause.

Opera
Depuis l’adoption du moteur Webkit, Opera présente le même comportement que Chrome. setInterval est limité à 1000 ms et requestAnimationFrame est suspendu lorsque l'onglet est inactif.

Sommaire

Intervalles répétés pour les onglets inactifs:

setIntervalrequestAnimationFrameChrome
 9- non affecté non pris en charge 
 10 non affecté en pause 
 11+> = 1000 ms en pause 
 
Firefox
 3- non affecté non pris en charge 
 4 non affecté 1s 
 5+> = 1000ms 2ns (n = nombre d'images depuis l'inactivité) 
 
IE
 9- non affecté non pris en charge 
 10+ non affecté mis en pause 
 
Bord
 13- non affecté en pause 
 14+> = 1000 ms en pause 
 
Safari
 5- non affecté non pris en charge 
 6 non affecté en pause 
 7+> = 1000 ms en pause 
 
Opera
 12- non affecté non pris en charge 
 15+> = 1000 ms en pause 
176
Antony

Ce que j’ai observé: sur des onglets inactifs dans Chrome , tous vos setTimeout (doivent être identiques pour setInterval) en attente moins que 1000ms sont arrondis à 1000ms. Je pense que les délais d'attente plus longs ne sont pas modifiés.

Cela 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 que cela se comporte de la sorte lorsque toute la fenêtre est inactive (mais cela semble assez facile à étudier).

10
user1321425