Ich habe setInterval
30 Mal pro Sekunde einen Code ausgeführt. Dies funktioniert jedoch hervorragend. Wenn ich jedoch eine andere Registerkarte auswähle (sodass die Registerkarte mit meinem Code inaktiv wird), setInterval
wird die Registerkarte aus irgendeinem Grund in den Ruhezustand versetzt.
Ich habe diesen vereinfachten Testfall erstellt ( http://jsfiddle.net/7f6DX/3/ ):
var $div = $('div');
var a = 0;
setInterval(function() {
a++;
$div.css("left", a)
}, 1000 / 30);
Wenn Sie diesen Code ausführen und dann zu einer anderen Registerkarte wechseln, einige Sekunden warten und zurückgehen, wird die Animation an dem Punkt fortgesetzt, an dem Sie zur anderen Registerkarte gewechselt haben. Die Animation wird also nicht 30 Mal pro Sekunde ausgeführt, falls die Registerkarte inaktiv ist. Dies kann bestätigt werden, indem gezählt wird, wie oft die setInterval
Funktion pro Sekunde aufgerufen wird. Dies ist nicht 30, sondern nur 1 oder 2, wenn die Registerkarte inaktiv ist.
Ich denke, dass dies beabsichtigt ist, um die Leistung zu verbessern, aber gibt es eine Möglichkeit, dieses Verhalten zu deaktivieren? In meinem Szenario ist das eigentlich ein Nachteil.
quelle
Date
Objekt gehackt, um wirklich zu sehen, welche Zeit vergangen ist.Date
. Wenn die Intervalle (aus diesem oder anderen Gründen) nicht schnell ausgelöst werden, wird die Animation nur ruckeliger und nicht langsamer.Antworten:
In den meisten Browsern haben inaktive Registerkarten eine Ausführung mit niedriger Priorität. Dies kann sich auf JavaScript-Timer auswirken.
Wenn die Werte Ihres Übergangs unter Verwendung von Echtzeit berechnet wurden, die zwischen Frames verstrichen ist, statt fester Inkremente in jedem Intervall, können Sie dieses Problem nicht nur umgehen, sondern auch eine flüssigere Animation erzielen, indem Sie requestAnimationFrame verwenden, da es bis zu 60 fps erreichen kann, wenn der Prozessor dies nicht tut sehr beschäftigt.
Hier ist ein Vanille-JavaScript-Beispiel für einen animierten Eigenschaftsübergang mit
requestAnimationFrame
:Für Hintergrundaufgaben (nicht UI-bezogen)
@ UpTheCreek Kommentar:
Wenn Sie Hintergrundaufgaben haben die Bedürfnisse genau in vorgegebenen Intervallen ausgeführt werden, können Sie mit HTML5 Web Worker . Schauen Sie sich Möhres Antwort unten an, um weitere Details zu erfahren ...
CSS vs JS "Animationen"
Dieses und viele andere Probleme könnten vermieden werden, indem CSS-Übergänge / Animationen anstelle von JavaScript-basierten Animationen verwendet werden, was einen erheblichen Overhead verursacht. Ich würde dieses jQuery-Plugin empfehlen , mit dem Sie wie die
animate()
Methoden von CSS-Übergängen profitieren können.quelle
before = now;
, um die seit dem Start verstrichene Zeit anstelle des Endes des vorherigen Aufrufs zu erhalten. Dies ist normalerweise das, was Sie wollen, wenn Sie Dinge animieren. Wenn eine Ausführung der IntervallfunktionelapsedTime
15 ms dauert, ergibt sich beim nächsten Aufruf (wenn die Registerkarte aktiv ist) 35 ms (anstelle von 50 ms, was das Intervall ist).Ich hatte das gleiche Problem mit Audio-Fading und HTML5-Player. Es blieb hängen, als der Tab inaktiv wurde. Daher habe ich herausgefunden, dass ein WebWorker Intervalle / Timeouts ohne Einschränkung verwenden darf. Ich benutze es, um "Ticks" im Haupt-Javascript zu posten.
WebWorkers Code:
Haupt-Javascript:
quelle
Es gibt eine Lösung für die Verwendung von Web Workern (wie bereits erwähnt), da diese in einem separaten Prozess ausgeführt werden und nicht verlangsamt werden
Ich habe ein winziges Skript geschrieben, das ohne Änderungen an Ihrem Code verwendet werden kann - es überschreibt einfach die Funktionen setTimeout, clearTimeout, setInterval, clearInterval.
Fügen Sie es einfach vor Ihrem gesamten Code ein.
Mehr Infos hier
quelle
Mach das einfach:
Inaktive Browser-Registerkarten puffern einige
setInterval
odersetTimeout
Funktionen.stop(true,true)
stoppt alle gepufferten Ereignisse und führt sofort nur die letzte Animation aus.Die
window.setTimeout()
Methode klemmt jetzt so, dass in inaktiven Registerkarten nicht mehr als eine Zeitüberschreitung pro Sekunde gesendet wird. Außerdem werden verschachtelte Zeitüberschreitungen jetzt auf den kleinsten Wert begrenzt, der in der HTML5-Spezifikation zulässig ist: 4 ms (anstelle der 10 ms, an die geklemmt wurde).quelle
Ich denke, dass ein bestes Verständnis für dieses Problem in diesem Beispiel besteht: http://jsfiddle.net/TAHDb/
Ich mache hier eine einfache Sache:
Halten Sie ein Intervall von 1 Sekunde ein und verbergen Sie jedes Mal die erste Spanne, verschieben Sie sie auf die letzte und zeigen Sie die zweite Spanne an.
Wenn Sie auf der Seite bleiben, funktioniert es wie angenommen. Wenn Sie die Registerkarte jedoch einige Sekunden lang ausblenden, sehen Sie bei Ihrer Rückkehr ein seltsames Element.
Es ist wie bei allen Ereignissen, die während der Zeit, in der Sie inaktiv waren, nicht aufgetreten sind, alles in einem Mal. Für einige Sekunden erhalten Sie also X-Ereignisse. Sie sind so schnell, dass alle 6 Bereiche gleichzeitig angezeigt werden können.
Chromnähte verzögern also nur die Ereignisse. Wenn Sie also zurückkommen, treten alle Ereignisse auf, aber alle auf einmal ...
Eine praktische Anwendung war dies für eine einfache Diashow. Stellen Sie sich vor, die Zahlen sind Bilder, und wenn der Benutzer bei seiner Rückkehr mit ausgeblendeten Registerkarten bleibt, werden alle Bilder schwebend angezeigt.
Um dies zu beheben, verwenden Sie den Stopp (true, true), wie von pimvdb angegeben. Dadurch wird die Ereigniswarteschlange gelöscht.
quelle
requestAnimationFrame
jQuery. Aufgrund einiger Macken (wie dieser) haben sie es entfernt. In 1.7 sehen Sie dieses Verhalten nicht. jsfiddle.net/TAHDb/1 . Da das Intervall einmal pro Sekunde ist, wirkt sich dies nicht auf das von mir veröffentlichte Problem aus, da das Maximum für inaktive Registerkarten auch einmal pro Sekunde beträgt - das macht also keinen Unterschied.Für mich ist es nicht wichtig, Audio im Hintergrund abzuspielen, wie für andere hier. Mein Problem war, dass ich einige Animationen hatte und sie sich wie verrückt verhielten, wenn Sie sich in anderen Registerkarten befanden und zu ihnen zurückkehrten. Meine Lösung bestand darin, diese Animationen einzufügen, wenn dadurch ein inaktiver Tab verhindert wird :
Dank dessen lief meine Animation nur, wenn der Tab aktiv war. Ich hoffe, das hilft jemandem bei meinem Fall.
quelle
setInterval(() => !document.hidden && myfunc(), 1000)
und es funktioniert perfektBeides
setInterval
undrequestAnimationFrame
funktioniert nicht, wenn die Registerkarte inaktiv ist oder funktioniert, aber nicht zum richtigen Zeitpunkt. Eine Lösung besteht darin, eine andere Quelle für Zeitereignisse zu verwenden. Beispielsweise sind Web-Sockets oder Web-Worker zwei Ereignisquellen, die einwandfrei funktionieren, wenn die Registerkarte inaktiv ist. Sie müssen also nicht Ihren gesamten Code auf einen Web-Worker verschieben, sondern nur Worker als Zeitereignisquelle verwenden:.
jsfiddle Link dieses Beispiels.
quelle
Ich bin stark von Ruslan Tushovs Bibliothek beeinflusst und habe meine eigene kleine Bibliothek erstellt . Fügen Sie einfach das Skript in das
<head>
und es wird gepatchtsetInterval
undsetTimeout
mit denen, die verwendenWebWorker
.quelle
Durch das Abspielen einer Audiodatei wird vorerst die volle Javascript-Hintergrundleistung sichergestellt
Für mich war es die einfachste und am wenigsten aufdringliche Lösung - abgesehen von einem schwachen / fast leeren Klang gibt es keine weiteren möglichen Nebenwirkungen
Details finden Sie hier: https://stackoverflow.com/a/51191818/914546
(Aus anderen Antworten geht hervor, dass einige Benutzer unterschiedliche Eigenschaften des Audio-Tags verwenden. Ich frage mich, ob es möglich ist, das Audio-Tag für die volle Leistung zu verwenden, ohne tatsächlich etwas abzuspielen.)
quelle
Hier ist meine grobe Lösung
quelle
postMessageHandler
ruft sein eigenes Ereignis auf, das er behandelt, wodurch eine Endlosschleife entsteht, die die Benutzeroberfläche nicht blockiert. Und während es sich um eine Endlosschleife handelt, prüft es bei jeder Ereignisbehandlung, ob eine Timeout- oder Intervallfunktion ausgeführt werden muss.Hinweis: Diese Lösung ist nicht geeignet, wenn Sie möchten, dass Ihr Intervall im Hintergrund ausgeführt wird, z. B. beim Abspielen von Audio oder ... Wenn Sie jedoch verwirrt sind, dass Ihre Animation beim Zurückkehren zu Ihrer Seite (Registerkarte) nicht ordnungsgemäß funktioniert, ist dies der Fall eine gute Lösung.
Es gibt viele Möglichkeiten, um dieses Ziel zu erreichen. Vielleicht sind die "WebWorker" die Standardmethoden, aber sicherlich nicht die einfachsten und praktischsten, insbesondere wenn Sie nicht genug Zeit haben, können Sie dies folgendermaßen versuchen:
► GRUNDKONZEPT:
1- Erstellen Sie einen Namen für Ihr Intervall (oder Ihre Animation) und legen Sie Ihr Intervall (Animation) fest, damit es ausgeführt wird, wenn der Benutzer Ihre Seite zum ersten Mal öffnet:
var interval_id = setInterval(your_func, 3000);
2-by
$(window).focus(function() {});
und$(window).blur(function() {});
Sie könnenclearInterval(interval_id)
jedes Mal, wenn der Browser (Tab) deaktiviert ist und Ihr Intervall (Animation) jedes Mal neu ausführen, wenn der Browser (Tab) wieder aktiv wirdinterval_id = setInterval();
►MUSTERCODE:
quelle
Ich denke, dass der einfachste Weg, dies jetzt zu erreichen
jQuery 3.3.x
, die Verwendung dieser Funktion ist:intervalFunction()
wird beim Laden der Seite sofort initialisiert. Wenn Ihr Fokus wieder vorhanden ist, versuchen Sie, das Intervall wieder zu aktivieren. Wenn Ihre Seite jedoch den Fokus verliert, können Sie jederzeit darauf zurückgreifen.Es ist klar und einfach. Zusätzlich diese Lösungen nicht verwenden veraltete Funktion wie
.focus()
,.focusin()
und.focusout()
quelle
Es ist eine ziemlich alte Frage, aber ich bin auf dasselbe Problem gestoßen.
Wenn Sie Ihr Web auf Chrome ausführen, können Sie diesen Beitrag Hintergrund-Registerkarten in Chrome 57 lesen .
Grundsätzlich könnte der Intervall-Timer ausgeführt werden, wenn das Timer-Budget nicht aufgebraucht ist.
Der Verbrauch des Budgets basiert auf der CPU-Zeitauslastung der Aufgabe innerhalb des Timers.
Basierend auf meinem Szenario zeichne ich Videos auf Leinwand und transportiere sie zu WebRTC.
Die webrtc-Videoverbindung wird ständig aktualisiert, auch wenn die Registerkarte inaktiv ist.
Sie müssen jedoch
setInterval
anstelle von verwendenrequestAnimationFrame
.Es wird jedoch nicht für das Rendern der Benutzeroberfläche empfohlen.
Es wäre besser, das
visibilityChange
Ereignis zuzuhören und den Render-Mechenismus entsprechend zu ändern.Außerdem könnten Sie @ kaan-soral ausprobieren und es sollte basierend auf der Dokumentation funktionieren.
quelle
Ich konnte meine Rückruffunktion mit einem Audio-Tag von mindestens 250 ms aufrufen und das Ereignis ontimeupdate verarbeiten. Es wird 3-4 mal in einer Sekunde aufgerufen. Es ist besser als eine Sekunde hinter setTimeout
quelle