EMZETT.
Login

Kurz: JavaScript führt Code in einem Ablauf (Thread) aus und kann trotzdem Timer, Klicks und Netzwerkantworten bedienen. Das Geheimnis ist die Event Loop.

Teil des Kurses JavaScript

Kapitel 27 von 40 im Kurs JavaScript. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

JavaScript führt Code in einem Ablauf (Thread) aus und kann trotzdem Timer, Klicks und Netzwerkantworten bedienen. Das Geheimnis ist die Event Loop.

Timer

FunktionWirkung
setTimeout(f, ms)f einmal nach ms Millisekunden
setInterval(f, ms)f wiederholt alle ms Millisekunden
clearTimeout(id), clearInterval(id)Timer abbrechen
requestAnimationFrame(f)vor dem nächsten Bildaufbau (nur Browser)
queueMicrotask(f)sofort nach dem aktuellen Code
let n = 0;
const id = setInterval(() => {
  n++;
  console.log("Tick", n);
  if (n === 3) {
    clearInterval(id);
    console.log("gestoppt");
  }
}, 20);
 
const abbruch = setTimeout(() => console.log("wird nie ausgegeben"), 500);
clearTimeout(abbruch);

Ausgabe:

Tick 1
Tick 2
Tick 3
gestoppt

Wie die Event Loop arbeitet

  1. Der Call Stack führt den aktuellen Code aus.
  2. Langsame Aufgaben (Timer, Netzwerk) übernimmt der Browser/Node im Hintergrund.
  3. Wenn sie fertig sind, landet ihr Callback in einer Warteschlange.
  4. Sobald der Call Stack leer ist, holt die Event Loop den nächsten Callback.

Es gibt zwei Warteschlangen mit Vorrang:

WarteschlangeBeispieleWann
MicrotasksPromise-Callbacks, queueMicrotaskdirekt nach dem aktuellen Code, vor allem anderen
MacrotasksTimer, Klicks, I/Odanach, einer pro Runde
console.log("1 synchron");
setTimeout(() => console.log("5 Timer (Macrotask)"), 0);
Promise.resolve().then(() => console.log("3 Promise (Microtask)"));
queueMicrotask(() => console.log("4 queueMicrotask"));
(async () => {
  console.log("2 async-Funktion läuft synchron bis zum ersten await");
  await null;
  console.log("4b nach await (Microtask)");
})();

Ausgabe:

1 synchron
2 async-Funktion läuft synchron bis zum ersten await
3 Promise (Microtask)
4 queueMicrotask
4b nach await (Microtask)
5 Timer (Macrotask)

Den Ablauf nicht blockieren

Ein langer Code-Block hält alles an: Die Seite reagiert nicht mehr, Timer verspäten sich.

const start = Date.now();
setTimeout(() => console.log("Timer verspätet:", Date.now() - start >= 200), 0);
while (Date.now() - start < 200) { /* blockiert 200 ms */ }
console.log("Schleife fertig");

Ausgabe:

Schleife fertig
Timer verspätet: true

Gegenmittel:

  • Arbeit in kleine Stücke teilen und zwischendurch setTimeout(..., 0) oder await einschieben
  • Schwere Berechnungen in einen Web Worker (Browser) oder Worker Thread (Node.js) auslagern
  • Auf Fortschritt asynchron warten statt in einer Schleife abzufragen

Arbeit in Stücke teilen

const pause = () => new Promise(r => setTimeout(r, 0));
async function summiere(bis) {
  let summe = 0;
  for (let i = 1; i <= bis; i++) {
    summe += i;
    if (i % 250000 === 0) await pause();     // gibt der Event Loop Luft
  }
  return summe;
}
summiere(1000000).then(s => console.log("Summe:", s));
setTimeout(() => console.log("Timer kam zwischendurch dran"), 0);

Ausgabe:

Timer kam zwischendurch dran
Summe: 500000500000

Debounce und Throttle

Bei häufigen Ereignissen (Tippen, Scrollen) willst du nicht jedes Mal reagieren:

function debounce(fn, ms) {
  let id;
  return (...args) => {
    clearTimeout(id);
    id = setTimeout(() => fn(...args), ms);
  };
}
const suche = debounce(text => console.log("Suche nach:", text), 50);
suche("j"); suche("ja"); suche("jav"); suche("java");

Ausgabe:

Suche nach: java

Debounce wartet, bis es ruhig ist, Throttle lässt höchstens eine Ausführung pro Zeitraum zu.

Merke

  • JavaScript hat einen Ablauf; langsame Dinge laufen im Hintergrund und melden sich per Callback
  • Microtasks (Promises) laufen vor Macrotasks (Timer, Events)
  • Lange Schleifen blockieren alles: aufteilen oder in einen Worker verlagern
  • setTimeout/setInterval mit clear... abbrechen
  • Debounce fasst schnelle Ereignisse zusammen

Übungsaufgabe

Baue einen Countdown von 5 bis 0 mit setInterval, der sich selbst beendet und am Schluss “Start!” ausgibt.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: async/await und fetch

Weiter: Das DOM: Elemente finden und ändern

Alle Kapitel: JavaScript im Überblick