Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Der Event Loop in JavaScript

Der Event Loop in JavaScript

~14 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Bevor wir zu Callbacks, Promises und async/await kommen, müssen wir verstehen, WIE JavaScript überhaupt Asynchronität handhabt – trotz eines einzigen, SINGLE-THREADED Ausführungsmodells.

JavaScript ist single-threaded

JavaScript führt zu jedem Zeitpunkt GENAU EINE Codezeile aus – es gibt (anders als in Sprachen mit "echtem" Multithreading) keine parallel laufenden Threads innerhalb eines einzelnen JavaScript-Programms. Das wirft eine berechtigte Frage auf: Wie kann JavaScript dann Netzwerk-Anfragen, Timer und Datei-Lesevorgänge handhaben, OHNE dabei das gesamte Programm zu blockieren?

Der Call Stack

Der Call Stack verfolgt, welche Funktion gerade läuft und von welcher anderen Funktion sie aufgerufen wurde – GENAU der Mechanismus, der bei der Rekursion aus Kapitel 18 bei fehlendem Basisfall irgendwann überläuft ("Maximum call stack size exceeded").

function berechneSteuer(betrag) {
  return betrag * 0.19;
}

function formatiereBetrag(betrag) {
  const steuer = berechneSteuer(betrag); // Call Stack: [formatiereBetrag, berechneSteuer]
  return `${betrag} EUR (Steuer: ${steuer} EUR)`;
}

console.log(formatiereBetrag(100)); // Call Stack: [console.log, formatiereBetrag]

Browser-/Node.js-APIs: Auslagerung außerhalb der Engine

Zeitaufwendige Operationen wie setTimeout, Netzwerk-Requests oder Datei-Lesevorgänge werden NICHT von der JavaScript-Engine selbst ausgeführt – sie werden an die umgebende Laufzeitumgebung (Browser oder Node.js) DELEGIERT, die diese Arbeit AUSSERHALB des Call Stacks im Hintergrund erledigt, während JavaScript selbst mit dem restlichen Code weitermachen kann.

Callback Queue und der Event Loop

Ist eine ausgelagerte Operation fertig (z. B. ist die setTimeout-Zeit abgelaufen), wird ihre Callback-Funktion in eine Callback Queue (auch "Task Queue") eingereiht. Der Event Loop hat GENAU eine Aufgabe: er prüft PERMANENT, ob der Call Stack LEER ist – und schiebt, sobald das der Fall ist, die nächste wartende Callback-Funktion aus der Queue auf den Stack.

console.log('1: Start'); // läuft sofort, synchron

setTimeout(() => {
  console.log('3: Timeout-Callback'); // läuft erst, wenn der Call Stack LEER ist
}, 0); // selbst mit 0ms Verzögerung!

console.log('2: Ende'); // läuft sofort, synchron

// Tatsächliche Ausgabe-Reihenfolge:
// 1: Start
// 2: Ende
// 3: Timeout-Callback

Achtung: Selbst setTimeout(fn, 0) läuft NICHT sofort! Der Callback wird erst nach dem kompletten SYNCHRONEN Code ausgeführt, da der Event Loop erst nach VOLLSTÄNDIGER Leerung des Call Stacks eingreift. Diese "1, 2, 3"-Reihenfolge – nicht "1, 3, 2" – überrascht praktisch jeden JavaScript-Einsteiger beim ersten Mal.

Microtask Queue: Promises haben Vorrang

Es gibt tatsächlich ZWEI Warteschlangen: die "normale" Callback Queue (für setTimeout u. Ä.) und eine Microtask Queue (für Promises, Kapitel 24). Die Microtask Queue wird nach JEDEM einzelnen Synchron-Codeblock VOLLSTÄNDIG geleert, BEVOR der Event Loop auch nur EINE einzige Callback-Queue-Aufgabe verarbeitet:

console.log('1: Start');

setTimeout(() => console.log('4: Timeout'), 0);

Promise.resolve().then(() => console.log('3: Promise'));

console.log('2: Ende');

// Tatsächliche Ausgabe-Reihenfolge:
// 1: Start
// 2: Ende
// 3: Promise    <- Microtask VOR Timeout, obwohl beide NACH dem synchronen Code registriert wurden!
// 4: Timeout

Tipp: Diese Reihenfolge erklärt, warum async/await (Kapitel 25, das unter der Haube auf Promises basiert) in der Praxis oft "reaktionsschneller" wirkt als setTimeout-basierter Code – Promise-Callbacks werden IMMER bevorzugt abgearbeitet.

Warum das für unser Haushaltsbuch wichtig ist

In Kapitel 25/26 werden wir Transaktionen ASYNCHRON aus einer Datei laden – mit diesem Grundlagenwissen verstehen wir dann GENAU, warum sich der Code an bestimmten Stellen "pausiert" anfühlt und WANN welcher Code tatsächlich läuft.