JavaScript — ist eine Programmiersprache mit einer einsträngigen Natur, aber sie kann auch asynchrone Operationen verarbeiten. Dies ist dank des Event Loops möglich — einem Mechanismus, der es JavaScript ermöglicht, Code auszuführen, ohne den Hauptthread zu blockieren. In diesem Beitrag werden wir uns ansehen, wie der Event Loop funktioniert, warum er wichtig ist und wie man seine Besonderheiten richtig nutzt.
Grundlagen der Funktionsweise des Event Loops
Die Funktionsweise des Event Loops basiert auf drei Hauptkomponenten:
- Call Stack (Aufrufstapel) — der Ort, an dem synchrone Funktionen ausgeführt werden.
- Task Queue (Aufgabenwarteschlange) — eine Liste von Callbacks, die auf ihre Ausführung warten.
- Microtask Queue (Mikroaufgabenwarteschlange) — eine Warteschlange für Promises und andere Mikroaufgaben.
Betrachten wir ein Beispiel:
console.log("Anfang");
setTimeout(() => {
console.log("setTimeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("Ende");
Die erwartete Ausführungsreihenfolge:
-
console.log("Anfang")— wird sofort ausgegeben. -
setTimeoutverzögert die Ausführung des Callbacks in der Aufgabenwarteschlange. -
Promise.resolve().then(...)fügt den Callback in die Mikroaufgabenwarteschlange ein. -
console.log("Ende")— wird sofort ausgegeben. - Nach Abschluss des synchronen Codes überprüft der Event Loop die Mikroaufgabenwarteschlange —
console.log("Promise")wird ausgeführt. - Erst danach wird der Callback aus der Aufgabenwarteschlange ausgeführt —
console.log("setTimeout").
Das Ergebnis in der Konsole wird sein:
Anfang
Ende
Promise
setTimeout
Warum setTimeout(..., 0) nicht sofort ausgeführt wird?
setTimeout(..., 0) bedeutet nicht, dass die Funktion sofort ausgeführt wird. Es fügt den Callback in die Aufgabenwarteschlange ein, die erst nach der Ausführung aller Mikroaufgaben verarbeitet wird.
Ein Beispiel, wo dies gut sichtbar ist:
setTimeout(() => console.log("setTimeout"), 0);
for (let i = 0; i < 1e9; i++) {} // Blockieren des Hauptthreads
console.log("Ende der Schleife");
Hier wird setTimeout verzögert, bis die Schleife abgeschlossen ist, selbst wenn 0 Millisekunden eingestellt sind.
Verwendung von queueMicrotask
Wenn Sie Code früher als mit setTimeout ausführen möchten, können Sie queueMicrotask verwenden:
queueMicrotask(() => console.log("Mikroaufgabe"));
console.log("Hauptcode");
Das Ergebnis:
Hauptcode
Mikroaufgabe