Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.
Diese Funktion ist nicht Baseline, da sie in einigen der am weitesten verbreiteten Browser nicht funktioniert.
Die kooperative Terminplanung von Hintergrundaufgaben API (auch bekannt als die Background Tasks API oder die requestIdleCallback() API) ermöglicht es, Aufgaben zu definieren, die automatisch durch den Benutzeragenten ausgeführt werden, wenn festgestellt wird, dass hierfür freie Zeit zur Verfügung steht.
Hinweis: Diese API ist nicht verfügbar in Web Workers.
Der Hauptthread eines Webbrowsers ist um seine Ereignisschleife herum organisiert. Dieser Code zeichnet alle anstehenden Updates des derzeit angezeigten Document, führt den JavaScript-Code aus, der auf der Seite ausgeführt werden muss, nimmt Ereignisse von Eingabegeräten entgegen und weist diese den Elementen zu, die sie erhalten sollen. Darüber hinaus verwaltet die Ereignisschleife die Interaktionen mit dem Betriebssystem, Updates der Benutzeroberfläche des Browsers und mehr. Es handelt sich um einen extrem beschäftigten Codeabschnitt, und Ihr Haupt-JavaScript-Code kann direkt in diesem Thread zusammen mit allem anderen laufen. Sicherlich wird der meiste, wenn nicht sogar der gesamte Code, der in der Lage ist, Änderungen am DOM vorzunehmen, im Hauptthread ausgeführt, da Änderungen an der Benutzeroberfläche üblicherweise nur im Hauptthread verfügbar sind.
Da die Ereignisbehandlung und Bildschirmaktualisierungen zwei der offensichtlichsten Möglichkeiten sind, wie Benutzer Leistungsprobleme bemerken, ist es wichtig, dass Ihr Code ein guter Bürger des Webs ist und hilft, Wartezeiten in der Ausführung der Ereignisschleife zu verhindern. In der Vergangenheit gab es keine zuverlässige Möglichkeit, dies zu tun, außer den Code so effizient wie möglich zu schreiben und so viel Arbeit wie möglich auf Workers auszulagern. Window.requestIdleCallback() ermöglicht es, sich aktiv daran zu beteiligen, sicherzustellen, dass die Ereignisschleife des Browsers reibungslos läuft, indem es dem Browser erlaubt, Ihren Code darüber zu informieren, wie viel Zeit er sicher nutzen kann, ohne das System zu verlangsamen. Wenn Sie sich innerhalb des vorgegebenen Limits halten, können Sie das Nutzungserlebnis des Benutzers erheblich verbessern.
Da Leerlaufrückrufe dazu gedacht sind, Ihrem Code eine Möglichkeit zu geben, mit der Ereignisschleife zu kooperieren, um sicherzustellen, dass das System in vollem Umfang genutzt wird, ohne es zu überlasten und so Verzögerungen oder andere Leistungsprobleme zu verursachen, sollten Sie sorgfältig überlegen, wie Sie sie einsetzen.
Die Background Tasks API fügt nur eine neue Schnittstelle hinzu:
IdleDeadlineEin Objekt dieses Typs wird dem Leerlaufrückruf übergeben, um eine Schätzung darüber bereitzustellen, wie lange der Leerlaufzeitraum voraussichtlich andauert und ob der Rückruf ausgeführt wird, weil sein Zeitüberschreitungszeitraum abgelaufen ist.
Die Window-Schnittstelle wird auch durch diese API erweitert, um die neuen Methoden requestIdleCallback() und cancelIdleCallback() anzubieten.
In diesem Beispiel werden wir uns ansehen, wie Sie requestIdleCallback() verwenden können, um zeitaufwändige, niedriger-priorisierte Aufgaben während der Zeit auszuführen, in der der Browser ansonsten im Leerlauf wäre. Darüber hinaus wird in diesem Beispiel gezeigt, wie Dokumentinhalte mit requestAnimationFrame() aktualisiert werden können.
Unten finden Sie nur das HTML und JavaScript für dieses Beispiel. Das CSS wird nicht angezeigt, da es nicht besonders entscheidend für das Verständnis dieser Funktionalität ist.
Um zu verstehen, was wir erreichen wollen, werfen wir einen Blick auf das HTML. Dies etabliert ein Kästchen (id="container"), das verwendet wird, um den Fortschritt einer Operation zu präsentieren (denn man weiß ja nie, wie lange das Dekodieren von "quantum filament tachyon emissions" dauern wird), sowie ein zweites Hauptkästchen (id="logBox"), das zur Anzeige von Textausgaben verwendet wird.
Das Fortschrittskästchen verwendet ein <progress>-Element, um den Fortschritt anzuzeigen, zusammen mit einem Label mit Abschnitten, die geändert werden, um numerische Informationen über den Fortschritt zu präsentieren. Darüber hinaus gibt es einen "Start"-Button (kreativ mit der ID "startButton" versehen), den der Benutzer verwenden wird, um die Datenverarbeitung zu starten.
Nun, da die Dokumentstruktur definiert ist, konstruieren Sie den JavaScript-Code, der die Arbeit erledigen soll. Das Ziel: Die Fähigkeit, der Warteschlange Anfragen hinzuzufügen, um Funktionen aufzurufen, mit einem Leerlaufrückruf, der diese Funktionen ausführt, wann immer das System lang genug im Leerlauf ist, um Fortschritte zu erzielen.
Diese Variablen werden verwendet, um die Liste der Aufgaben zu verwalten, die darauf warten, ausgeführt zu werden, sowie Statusinformationen über die Aufgabenwarteschlange und deren Ausführung:
Als nächstes haben wir Variablen, die auf die DOM-Elemente verweisen, mit denen wir interagieren müssen. Diese Elemente sind:
Schließlich richten wir ein paar Variablen für andere Elemente ein:
Als nächstes schauen wir uns an, wie wir die Aufgaben verwalten, die durchgeführt werden müssen. Wir werden dies tun, indem wir eine FIFO-Warteschlange von Aufgaben erstellen, die wir ausführen, sobald Zeit dafür im Leerlaufrückrufszeitraum ist.
Aufgaben in die Warteschlange stellenZuerst benötigen wir eine Funktion, die Aufgaben für die zukünftige Ausführung in die Warteschlange stellt. Diese Funktion, enqueueTask(), sieht wie folgt aus:
enqueueTask() nimmt zwei Parameter als Eingabe entgegen:
Um die Aufgabe in die Warteschlange zu stellen, fgen wir ein Objekt zum taskList-Array hinzu; das Objekt enthält die Werte taskHandler und taskData unter den Namen handler und data, und dann erhöhen wir totalTaskCount, das die Gesamtzahl der jemals in die Warteschlange gestellten Aufgaben reflektiert (wir verringern es nicht, wenn Aufgaben aus der Warteschlange entfernt werden).
Als nächstes prüfen wir, ob bereits ein Leerlaufrückruf erstellt wurde; wenn taskHandle 0 ist, wissen wir, dass noch kein Leerlaufrückruf vorhanden ist, also rufen wir requestIdleCallback() auf, um einen zu erstellen. Es ist so konfiguriert, dass es eine Funktion namens runTaskQueue() aufruft, die wir uns in Kürze ansehen werden, und mit einem timeout von 1 Sekunde, damit sie mindestens einmal pro Sekunde ausgeführt wird, selbst wenn keine tatsächliche Leerlaufzeit verfügbar ist.
Aufgaben ausführenUnser Leerlaufrückruf-Handler, runTaskQueue(), wird aufgerufen, wenn der Browser feststellt, dass es genügend verfügbare Leerlaufzeit gibt, um uns einige Arbeiten erledigen zu lassen, oder unser Timeout von einer Sekunde abläuft. Die Aufgabe dieser Funktion besteht darin, unsere in die Warteschlange gestellten Aufgaben auszuführen.
Der Kern von runTaskQueue() ist eine Schleife, die so lange läuft, wie Zeit übrig ist (wie durch die Überprüfung von deadline.timeRemaining festgelegt wird), um sicherzustellen, dass sie mehr als 0 beträgt oder das Zeitlimit erreicht wurde (deadline.didTimeout ist wahr), und solange noch Aufgaben in der Aufgabenliste stehen.
Für jede Aufgabe in der Warteschlange, die wir ausführen können, tun wir Folgendes:
Wenn die Zeit abläuft und noch Aufgaben in der Liste stehen, rufen wir erneut requestIdleCallback() auf, damit wir die Aufgaben beim nächsten Mal, wenn Leerlaufzeit verfügbar ist, weiter verarbeiten können. Wenn die Warteschlange leer ist, setzen wir taskHandle auf 0, um anzuzeigen, dass wir keinen Rückruf geplant haben. Auf diese Weise wissen wir, dass wir beim nächsten Aufruf von enqueueTask() einen Rückruf anfordern müssen.
Eine Sache, die wir tun möchten, ist, unser Dokument mit Protokollausgaben und Fortschrittsinformationen zu aktualisieren. Sie können jedoch das DOM nicht sicher aus einem Leerlaufrückruf heraus ändern. Stattdessen verwenden wir requestAnimationFrame(), um den Browser zu bitten, uns aufzurufen, wenn es sicher ist, die Anzeige zu aktualisieren.
Anzeigeaktualisierungen planenÄnderungen am DOM werden durch den Aufruf der Funktion scheduleStatusRefresh() geplant.
Dies ist eine einfache Funktion. Es wird überprüft, ob wir bereits eine Anzeigeaktualisierung geplant haben, indem der Wert von statusRefreshScheduled überprüft wird. Falls false, rufen wir requestAnimationFrame() auf, um eine Aktualisierung zu planen, indem die Funktion updateDisplay() bereitgestellt wird, um diese Arbeit zu erledigen.
Die Anzeige aktualisierenDie updateDisplay()-Funktion ist verantwortlich für das Zeichnen der Inhalte des Fortschrittskästchens und des Protokolls. Sie wird vom Browser aufgerufen, wenn das DOM in einem sicheren Zustand ist, um Änderungen während des Renderns des nächsten Frames vorzunehmen.
Zuerst wird scrolledToEnd auf true gesetzt, wenn der Text im Protokoll bis zum Ende gescrollt ist; andernfalls wird es auf false gesetzt. Wir verwenden das, um zu bestimmen, ob wir die Bildlaufposition aktualisieren sollten, um sicherzustellen, dass das Protokoll am Ende bleibt.
Als nächstes aktualisieren wir die Fortschritts- und Statusinformationen, wenn Aufgaben in die Warteschlange gestellt wurden.
Dann, wenn es Text gibt, der dem Protokoll hinzugefügt werden soll (das heißt, wenn logFragment nicht null ist), fügen wir ihn dem Protokollelement mit Element.appendChild() hinzu und setzen logFragment auf null, damit wir es nicht erneut hinzufügen.
Wenn das Protokoll zu Beginn bis ganz zum Ende gescrollt war, stellen wir sicher, dass es das immer noch ist. Dann setzen wir statusRefreshScheduled auf false, um anzuzeigen, dass wir die Aktualisierung durchgeführt haben und es sicher ist, eine neue anzufordern.
Die log()-Funktion fügt den angegebenen Text dem Protokoll hinzu. Da wir beim Aufruf von log() nicht wissen, ob es sicher ist, das DOM sofort zu berühren, werden wir den Protokolltext zwischenspeichern, bis es sicher ist, die Aktualisierung vorzunehmen. Oben im Code für updateDisplay() finden Sie den Code, der tatsächlich den protokollierten Text zu dem Protokollelement hinzufügt, wenn der Animations-Frame aktualisiert wird.
Zunächst erstellen wir ein DocumentFragment-Objekt namens logFragment, wenn derzeit keines existiert. Dieses Element ist ein Pseudo-DOM, in das wir Elemente einfügen können, ohne sofort das Haupt-DOM selbst zu ändern.
Dann erstellen wir ein neues <div>-Element und setzen dessen Inhalt auf den Eingabe-text. Dann hängen wir das neue Element an das Ende des Pseudo-DOMs in logFragment. logFragment wird Protokolleinträge bis zum nächsten Aufruf von updateDisplay() ansammeln, wenn das DOM bereit ist für die Änderungen.
Nun, da wir den Aufgabenverwaltungs- und Anzeigewartungscode abgeschlossen haben, können wir tatsächlich den Code einrichten, um Aufgaben auszuführen, die Arbeit erledigen.
Die Funktion, die wir als unseren Aufgabenverwalter verwenden werden—das heißt die Funktion, die als Wert der handler-Eigenschaft des Aufgabenobjekts verwendet wird—ist logTaskHandler(). Es ist eine einfache Funktion, die für jede Aufgabe eine Menge Zeug im Protokoll ausgibt. In Ihrer eigenen Anwendung würden Sie diesen Code durch die Aufgabe ersetzen, die Sie während der Leerlaufzeit ausführen möchten. Denken Sie nur daran, dass alles, was Sie ändern möchten, das DOM betrifft, durch requestAnimationFrame() gehandhabt werden muss.
Alles wird ausgelöst, wenn der Benutzer auf den Start-Button klickt, wodurch die decodeTechnoStuff()-Funktion aufgerufen wird.
decodeTechnoStuff() beginnt damit, die Werte von totalTaskCount (die Anzahl der bisher zur Warteschlange hinzugefügten Aufgaben) und currentTaskNumber (die derzeit ausgeführte Aufgabe) auf Null zu setzen und dann updateDisplay() aufzurufen, um die Anzeige in ihren "nichts ist passiert"-Zustand zurückzusetzen.
In diesem Beispiel wird eine zufällige Anzahl von Aufgaben erstellt (zwischen 100 und 200). Dazu verwenden wir die getRandomIntInclusive()-Funktion, die als Beispiel in der Dokumentation von Math.random() bereitgestellt wird, um die Anzahl der zu erstellenden Aufgaben zu erhalten.
Dann starten wir eine Schleife, um die tatsächlichen Aufgaben zu erstellen. Für jede Aufgabe erstellen wir ein Objekt taskData, das zwei Eigenschaften enthält:
Jede Aufgabe wird dann durch einen Anruf von enqueueTask() in die Warteschlange gestellt, wobei logTaskHandler() als Verarbeitungsfunktion und das taskData-Objekt als das objekt, das in die Funktion übergeben wird, wenn sie aufgerufen wird.
Unten ist das tatsächliche funktionierende Ergebnis des obenstehenden Codes. Probieren Sie es aus, spielen Sie damit in den Entwicklertools Ihres Browsers und experimentieren Sie, wie Sie es in Ihrem eigenen Code verwenden können.
| requestIdleCallback() # the-requestidlecallback-method |
JavaScript aktivieren, um diese Browser-Kompatibilitätstabelle anzuzeigen.
Der Bauplan für ein besseres Internet.
Besuche die gemeinnützige Muttergesellschaft der Mozilla Corporation, die Mozilla Foundation.
Teile dieses Inhalts sind ©1998–2026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfügbar unter einer Creative-Commons-Lizenz.