J'ai setInterval
un morceau de code en cours d'exécution 30 fois par seconde. Cela fonctionne très bien, cependant lorsque je sélectionne un autre onglet (afin que l'onglet avec mon code devienne inactif), le setInterval
est mis à un état inactif pour une raison quelconque.
J'ai fait ce cas de test simplifié ( http://jsfiddle.net/7f6DX/3/ ):
var $div = $('div');
var a = 0;
setInterval(function() {
a++;
$div.css("left", a)
}, 1000 / 30);
Si vous exécutez ce code, puis passez à un autre onglet, attendez quelques secondes et revenez en arrière, l'animation continue au point où elle se trouvait lorsque vous êtes passé à l'autre onglet. Ainsi, l'animation ne s'exécute pas 30 fois par seconde au cas où l'onglet serait inactif. Cela peut être confirmé en comptant le nombre de fois où la setInterval
fonction est appelée chaque seconde - ce ne sera pas 30 mais juste 1 ou 2 si l'onglet est inactif.
Je suppose que cela est fait par conception afin d'améliorer les performances, mais existe-t-il un moyen de désactiver ce comportement? C'est en fait un inconvénient dans mon scénario.
Date
objet pour vraiment voir le temps écoulé.Date
. Ainsi, lorsque les intervalles ne se déclenchent pas rapidement (pour cela ou pour d'autres raisons), l'animation devient plus saccadée, pas plus lente.Réponses:
Sur la plupart des navigateurs, les onglets inactifs ont une exécution de faible priorité, ce qui peut affecter les minuteries JavaScript.
Si les valeurs de votre transition ont été calculées en utilisant le temps réel écoulé entre les images au lieu d'incréments fixes sur chaque intervalle, vous pouvez non seulement contourner ce problème, mais également obtenir une animation plus douce en utilisant requestAnimationFrame car il peut atteindre 60fps si le processeur ne l'est pas très occupé.
Voici un exemple JavaScript vanille d'une transition de propriété animée utilisant
requestAnimationFrame
:Pour les tâches en arrière-plan (non liées à l'interface utilisateur)
Commentaire de @UpTheCreek:
Si vous avez des tâches d'arrière-plan qui doivent être exécutées avec précision à des intervalles donnés, vous pouvez utiliser HTML5 Web Workers . Jeter un coup d'œil à la réponse de Möhre ci-dessous pour plus de détails ...
"Animations" CSS vs JS
Ce problème et bien d'autres pourraient être évités en utilisant des transitions / animations CSS au lieu d'animations basées sur JavaScript, ce qui ajoute une surcharge considérable. Je recommanderais ce plugin jQuery qui vous permet de profiter des transitions CSS tout comme les
animate()
méthodes.la source
before = now;
pour obtenir le temps écoulé depuis le début au lieu de la fin de l'appel précédent. C'est généralement ce que vous voulez lorsque vous animez des choses. Dans l'état actuel des choses, si une exécution de la fonction d'intervalle prend 15 ms,elapsedTime
elle donnera 35 ms (au lieu de 50 ms qui est l'intervalle) la prochaine fois qu'elle sera appelée (lorsque l'onglet est actif).J'ai rencontré le même problème avec la décoloration audio et le lecteur HTML5. Il est resté bloqué lorsque l'onglet est devenu inactif. J'ai donc découvert qu'un WebWorker est autorisé à utiliser des intervalles / délais sans limitation. Je l'utilise pour poster des "ticks" sur le javascript principal.
Code WebWorkers:
Javascript principal:
la source
Il existe une solution pour utiliser les Web Workers (comme mentionné précédemment), car ils s'exécutent dans un processus séparé et ne sont pas ralentis
J'ai écrit un petit script qui peut être utilisé sans modification de votre code - il remplace simplement les fonctions setTimeout, clearTimeout, setInterval, clearInterval.
Incluez-le juste avant tout votre code.
Plus d'infos ici
la source
Faites juste ceci:
Les onglets de navigateur inactifs mettent en mémoire certaines des fonctions
setInterval
ousetTimeout
.stop(true,true)
arrêtera tous les événements mis en mémoire tampon et n'exécutera immédiatement que la dernière animation.La
window.setTimeout()
méthode empêche désormais d'envoyer plus d'un délai d'expiration par seconde dans les onglets inactifs. De plus, il limite désormais les délais d'attente imbriqués à la plus petite valeur autorisée par la spécification HTML5: 4 ms (au lieu des 10 ms auxquels il était habitué).la source
Je pense que la meilleure compréhension de ce problème est dans cet exemple: http://jsfiddle.net/TAHDb/
Je fais une chose simple ici:
Avoir un intervalle de 1 seconde et à chaque fois masquer le premier intervalle et le déplacer en dernier, et afficher le 2e intervalle.
Si vous restez sur la page, cela fonctionne comme prévu. Mais si vous cachez l'onglet pendant quelques secondes, lorsque vous reviendrez, vous verrez une chose bizarre.
C'est comme si tous les événements qui ne se sont pas produits pendant le temps où vous étiez inactif maintenant se produiront en une seule fois. donc pendant quelques secondes, vous obtiendrez des événements comme X. ils sont si rapides qu'il est possible de voir les 6 travées à la fois.
Donc, il semble que le chrome ne retarde que les événements, donc lorsque vous reviendrez, tous les événements se produiront mais tous à la fois ...
Une application pratique était celle-ci pour un simple diaporama. Imaginez que les nombres soient des images, et si l'utilisateur reste avec l'onglet caché à son retour, il verra toutes les images flottantes, totalement mesurées.
Pour résoudre ce problème, utilisez stop (true, true) comme indiqué par pimvdb. Cela effacera la file d'attente des événements.
la source
requestAnimationFrame
ce jQuery utilisé. En raison de certaines bizarreries (comme celle-ci), ils l'ont supprimé. Dans la version 1.7, vous ne voyez pas ce comportement. jsfiddle.net/TAHDb/1 . Parce que l'intervalle est une fois par seconde, cela n'affecte en fait pas le problème que j'ai publié, car le maximum pour les onglets inactifs est également une fois par seconde - donc cela ne fait aucune différence.Pour moi, ce n'est pas important de jouer de l'audio en arrière-plan comme pour d'autres ici, mon problème était que j'avais des animations et elles agissaient comme des fous quand vous étiez dans d'autres onglets et y reveniez. Ma solution était de mettre ces animations à l'intérieur si cela empêche l' onglet inactif :
grâce à cela, mon animation ne fonctionnait que si l'onglet était actif. J'espère que cela aidera quelqu'un avec mon cas.
la source
setInterval(() => !document.hidden && myfunc(), 1000)
et ça marche parfaitementLes deux
setInterval
etrequestAnimationFrame
ne fonctionnent pas lorsque l'onglet est inactif ou fonctionne mais pas aux bonnes périodes. Une solution consiste à utiliser une autre source pour les événements temporels. Par exemple, les sockets Web ou les travailleurs Web sont deux sources d'événements qui fonctionnent correctement lorsque l'onglet est inactif. Donc, pas besoin de déplacer tout votre code vers un web worker, utilisez simplement worker comme source d'événement temporel:.
jsfiddle lien de cet exemple.
la source
Fortement influencé par la bibliothèque de Ruslan Tushov, j'ai créé ma propre petite bibliothèque . Ajoutez simplement le script dans le
<head>
et il corrigerasetInterval
etsetTimeout
avec ceux qui utilisentWebWorker
.la source
La lecture d'un fichier audio garantit pour le moment des performances Javascript complètes en arrière-plan
Pour moi, c'était la solution la plus simple et la moins intrusive - à part jouer un son faible / presque vide, il n'y a pas d'autres effets secondaires potentiels
Vous pouvez trouver les détails ici: https://stackoverflow.com/a/51191818/914546
(À partir d'autres réponses, je vois que certaines personnes utilisent différentes propriétés de la balise Audio, je me demande s'il est possible d'utiliser la balise Audio pour des performances optimales, sans réellement jouer quelque chose)
la source
Remarque: cette solution ne convient pas si vous aimez que votre intervalle fonctionne en arrière-plan, par exemple en jouant de l'audio ou ... mais si vous êtes confus par exemple par le fait que votre animation ne fonctionne pas correctement en revenant sur votre page (onglet) c'est une bonne solution.
Il existe de nombreuses façons d'atteindre cet objectif, peut-être que le "WebWorkers" est le plus standard mais ce n'est certainement pas le plus simple et le plus pratique, surtout si vous n'avez pas assez de temps, vous pouvez donc essayer de cette façon:
►CONCEPT DE BASE:
1- Construisez un nom pour votre intervalle (ou animation) et définissez votre intervalle (animation), afin qu'il s'exécute lorsque l'utilisateur ouvre votre page pour la première fois:
var interval_id = setInterval(your_func, 3000);
2- par
$(window).focus(function() {});
et$(window).blur(function() {});
vous pouvez àclearInterval(interval_id)
chaque fois que le navigateur (onglet) est désactivé et réexécutez votre intervalle (animation) à chaque fois que le navigateur (onglet) serait réactivé parinterval_id = setInterval();
►EXEMPLE DE CODE:
la source
C'est une question assez ancienne mais j'ai rencontré le même problème.
Si vous exécutez votre site Web sur Chrome, vous pouvez lire cet article Onglets d'arrière-plan dans Chrome 57 .
Fondamentalement, le minuteur d'intervalle pourrait s'exécuter s'il n'a pas épuisé le budget du minuteur.
La consommation de budget est basée sur l'utilisation du temps CPU de la tâche dans le minuteur.
Sur la base de mon scénario, je dessine une vidéo sur un canevas et je la transporte vers WebRTC.
La connexion vidéo webrtc continuerait à se mettre à jour même si l'onglet est inactif.
Cependant, vous devez utiliser à la
setInterval
place derequestAnimationFrame
.il n'est cependant pas recommandé pour le rendu de l'interface utilisateur.
Il vaudrait mieux écouter
visibilityChange
événement et changer le rendu du mécénisme en conséquence.De plus, vous pouvez essayer @ kaan-soral et cela devrait fonctionner sur la base de la documentation.
la source
Voici ma solution approximative
la source
postMessageHandler
invoque son propre événement qu'il gère, ayant ainsi une boucle infinie qui ne bloque pas l'interface utilisateur. Et pendant qu'il boucle à l'infini, il vérifie avec chaque gestion d'événement s'il y a une fonction de temporisation ou d'intervalle à exécuter.J'ai pu appeler ma fonction de rappel à au moins 250 ms en utilisant une balise audio et en gérant son événement ontimeupdate. Son appelé 3-4 fois en une seconde. C'est mieux qu'une seconde ensemble de retard
la source