W3docs

JavaScript Microtasks

Die Microtask-Warteschlange in JavaScript priorisiert Callbacks und stellt sicher, dass sie nach dem aktuellen Skript, aber vor dem nächsten Macrotask ausgeführt werden.

In JavaScript ist die Microtask-Warteschlange eine wichtige Komponente des asynchronen Ausführungsmodells. Sie priorisiert bestimmte Callbacks und stellt sicher, dass diese nach dem aktuellen Skript, aber vor der Fortsetzung des Event Loop mit anderen Aufgaben wie dem Rendern oder der Verarbeitung von Benutzerereignissen ausgeführt werden. Dieser Leitfaden bietet einen tiefen Einblick in die effektive Nutzung der Microtask-Warteschlange zur Verbesserung von JavaScript-Anwendungen.

Den Event Loop und die Microtask-Warteschlange verstehen

Die JavaScript-Engine verwendet einen Event Loop, der die Ausführung von Skripten verwaltet und nicht blockierende Operationen ermöglicht. Die Microtask-Warteschlange ist Teil dieses Event Loop. Sie wird speziell für Promises (siehe JavaScript: Promises) und andere Operationen wie queueMicrotask verwendet und stellt sicher, dass diese am Ende des aktuellen Durchlaufs des JavaScript-Event-Loop, vor der Rendering-Phase, verarbeitet werden.

Es gibt zwei unterschiedliche Warteschlangen, die man im Blick behalten sollte:

  • Die Microtask-Warteschlange enthält Callbacks von aufgelösten/abgelehnten Promises und von queueMicrotask(). Nach jeder Aufgabe leert die Engine diese Warteschlange vollständig, bevor sie irgendetwas anderes tut.
  • Die Macrotask-Warteschlange (manchmal auch als Task-Warteschlange bezeichnet) enthält Callbacks von setTimeout, setInterval, I/O und UI-Ereignissen. Pro Schleifendurchlauf wird jeweils nur ein Macrotask ausgeführt.

Die wichtigste Regel: Wenn der aktuelle synchrone Code beendet ist, leert die Engine zuerst die gesamte Microtask-Warteschlange und wählt erst dann den nächsten Macrotask aus. Deshalb läuft ein Promise-Callback immer vor einem setTimeout(…, 0)-Callback, der zuvor geplant wurde. Einen vollständigen Überblick darüber, wie diese Warteschlangen interagieren, bietet Event Loop: Microtasks and Macrotasks.

Beispiel: Einfaches Promise


javascript— editable

In diesem Beispiel gibt die Konsole zuerst 'Script end' aus, gefolgt von 'Promise resolved'. Dies zeigt, wie JavaScript Promise-Auflösungen in die Microtask-Warteschlange verschiebt.

Wie funktioniert die Microtask-Warteschlange?

Die Microtask-Warteschlange führt Aufgaben aus, die als Microtasks geplant sind. Dazu gehören Operationen von:

  • Promises
  • Object.observe (veraltet)
  • MutationObserver
  • queueMicrotask() API

Jeder dieser Microtasks wird vollständig verarbeitet, bevor mit dem nächsten fortgefahren wird oder bevor ein Rendering oder andere Macrotasks ausgeführt werden.

Microtasks planen

Microtasks können direkt mit der Funktion queueMicrotask geplant werden. Diese Funktion nimmt einen Callback entgegen und fügt ihn zur Microtask-Warteschlange hinzu. Wie zu sehen ist, wird die Warteschlange ausgeführt, nachdem alle anderen Aufgaben abgeschlossen sind.


javascript— editable

Microtask vs. Macrotask: Warum ein Promise setTimeout(0) schlägt

Ein häufiger Verwirrungspunkt ist, warum ein Promise-Callback vor einem setTimeout(…, 0)-Callback ausgeführt wird, selbst wenn der Timer zuerst geplant wurde. Die Antwort liegt in der oben genannten Regel: Sobald synchroner Code endet, leert die Engine die gesamte Microtask-Warteschlange, bevor sie die Macrotask-Warteschlange anfasst, in der setTimeout-Callbacks leben. Selbst ein Timer mit null Verzögerung muss warten.


javascript— editable

Die Ausgabe ist immer:

1: synchronous start
2: synchronous end
3: promise (microtask)
4: setTimeout (macrotask)

Die Zeilen 1 und 2 werden zuerst ausgeführt, weil synchroner Code niemals unterbricht. Dann wird die Microtask-Warteschlange geleert (der Promise-Callback), und erst danach kommt der nächste Macrotask — der setTimeout-Callback — an die Reihe. Mehr über Timer erfahren Sie in Scheduling: setTimeout and setInterval.

Reihenfolge innerhalb der Microtask-Warteschlange

Microtasks selbst werden in der Reihenfolge ausgeführt, in der sie in die Warteschlange eingereiht wurden (FIFO). Das Mischen von .then()-Callbacks mit queueMicrotask() macht dies deutlich — beide speisen dieselbe Warteschlange, sodass das Ergebnis schlicht nach dem Prinzip „First-in, first-out" abläuft:


javascript— editable

Dies gibt start, end, promise 1, queueMicrotask, promise 2 aus. Zu beachten ist, dass ein Microtask, der von einem anderen Microtask geplant wird, zur selben Warteschlange hinzugefügt wird und im selben Leerungszyklus ausgeführt wird — vor jedem Rendering oder Macrotask. Genau das macht unkontrollierte Microtask-Schleifen in der Lage, den Rest der Seite auszuhungern.

Praktische Anwendungen von Microtasks

Microtasks sind besonders nützlich in komplexen Webanwendungen für Aufgaben, die unmittelbar nach dem aktuellen Skript, aber bevor das System andere Ereignisse verarbeitet oder die Benutzeroberfläche neu rendert, Aufmerksamkeit erfordern.

Szenario: Echtzeit-Datenverarbeitung

Betrachten wir ein Szenario, in dem Echtzeit-Daten von einem Server verarbeitet werden müssen, ohne die Benutzererfahrung zu unterbrechen:


javascript— editable

Dieses Beispiel demonstriert das asynchrone Abrufen von Daten, deren Verarbeitung und die Planung einer UI-Aktualisierung in der Microtask-Warteschlange.

Effektive Fehlerbehandlung in Promises

Eine effektive Fehlerbehandlung in asynchronem Code ist entscheidend. Die Verwendung der Microtask-Warteschlange mit der Promise-Fehlerbehandlung stellt sicher, dass Fehler unmittelbar nach der Auflösungslogik des Promise behandelt werden, aber vor anderen nicht zusammenhängenden Aufgaben.


javascript— editable

Best Practices für die Verwendung der Microtask-Warteschlange

  1. Aufgaben ordnen: Verstehen, wann Microtasks eingesetzt werden sollten, um eine korrekte Reihenfolge von Operationen sicherzustellen.
  2. Aushungerung vermeiden: Sicherstellen, dass die Microtask-Warteschlange nicht kontinuierlich neue Aufgaben erhält, was Macrotasks wie UI-Aktualisierungen am Ausführen hindern würde.
  3. Debugging: Die Ausführung von Microtasks verfolgen und debuggen, um unerwartete Verhaltensweisen in asynchronem Code zu vermeiden.

Fazit

Die Beherrschung der Microtask-Warteschlange in JavaScript ist für die Entwicklung fortgeschrittener, reaktionsschneller Anwendungen unerlässlich. Durch die effektive Nutzung dieser leistungsstarken Komponente des JavaScript-Ausführungsmodells können Entwickler flüssigere, nicht blockierende Interaktionen und eine verbesserte Benutzererfahrung gewährleisten. Diese Einführung vermittelt das grundlegende Wissen und die praktischen Fähigkeiten, um die Microtask-Warteschlange in jedem JavaScript-gesteuerten Projekt effektiv einzusetzen.

Übungen

Übung
Was ist ein Microtask in JavaScript?
Was ist ein Microtask in JavaScript?
Was this page helpful?