Synchron vs. Asynchron in JavaScript
Synchron vs. Asynchron in JavaScript
Bevor du Promises und async/await verstehen kannst, musst du den fundamentalen Unterschied zwischen synchronem und asynchronem Code verstehen.
Synchroner Code
Synchroner Code wird Zeile für Zeile ausgeführt. Jede Zeile wartet, bis die vorherige fertig ist.
console.log("Erste Zeile");
console.log("Zweite Zeile");
console.log("Dritte Zeile");
// Ausgabe (garantierte Reihenfolge):
// Erste Zeile
// Zweite Zeile
// Dritte Zeile
Das Problem mit synchronem Code
// Stell dir vor, diese Funktion braucht 5 Sekunden
function ladeDatenVomServer() {
// ... warte 5 Sekunden ...
return daten;
}
console.log("Start");
const daten = ladeDatenVomServer(); // Browser friert 5 Sekunden ein!
console.log("Daten geladen");
console.log("Weiter...");
// Während dieser 5 Sekunden:
// - Keine Klicks möglich
// - Keine Animationen
// - Seite reagiert nicht
// = Schlechte User Experience!
Asynchroner Code
Asynchroner Code blockiert nicht. Langsame Operationen laufen im Hintergrund, und der Rest des Codes läuft weiter.
console.log("Start");
setTimeout(() => {
console.log("Nach 2 Sekunden");
}, 2000);
console.log("Ende");
// Ausgabe:
// Start
// Ende
// (2 Sekunden Pause)
// Nach 2 Sekunden
Die Reihenfolge ist nicht von oben nach unten!
Warum brauchen wir asynchronen Code?
JavaScript läuft in einem Single Thread - es kann nur eine Sache gleichzeitig tun. Aber moderne Webapps müssen:
- Daten vom Server laden
- Dateien lesen/schreiben
- Auf User-Input warten
- Timer verwalten
- Animationen abspielen
All das gleichzeitig - ohne die UI zu blockieren.
Die Event Loop
JavaScript löst das mit der Event Loop:
┌─────────────────────────────┐
│ Call Stack │ ← Führt synchronen Code aus
└─────────────────────────────┘
↑
│ Nimmt Tasks
│
┌─────────────────────────────┐
│ Task Queue │ ← Fertige async Callbacks warten hier
└─────────────────────────────┘
↑
│ Schiebt fertige Tasks
│
┌─────────────────────────────┐
│ Web APIs / Browser │ ← setTimeout, fetch, Events laufen hier
└─────────────────────────────┘
console.log("1");
setTimeout(() => {
console.log("2");
}, 0); // Auch mit 0ms!
console.log("3");
// Ausgabe:
// 1
// 3
// 2 ← Kommt zuletzt, obwohl Timer 0ms!
// Warum?
// 1. "1" geht auf Call Stack → wird ausgeführt
// 2. setTimeout geht zu Web API → Timer startet
// 3. "3" geht auf Call Stack → wird ausgeführt
// 4. Timer fertig → Callback in Queue
// 5. Call Stack leer → Callback aus Queue auf Stack
// 6. "2" wird ausgeführt
Asynchrone Patterns in JavaScript
1. Callbacks (älteste Methode)
function ladeDaten(callback) {
setTimeout(() => {
const daten = { id: 1, name: "Max" };
callback(daten);
}, 1000);
}
console.log("Lade...");
ladeDaten((daten) => {
console.log("Daten:", daten);
});
console.log("Weiter...");
// Ausgabe:
// Lade...
// Weiter...
// (1 Sekunde)
// Daten: { id: 1, name: "Max" }
2. Promises (ES6)
function ladeDaten() {
return new Promise((resolve) => {
setTimeout(() => {
const daten = { id: 1, name: "Max" };
resolve(daten);
}, 1000);
});
}
console.log("Lade...");
ladeDaten().then((daten) => {
console.log("Daten:", daten);
});
console.log("Weiter...");
// Gleiche Ausgabe wie Callbacks
3. Async/Await (ES2017)
async function main() {
console.log("Lade...");
const daten = await ladeDaten();
console.log("Daten:", daten);
console.log("Weiter...");
}
main();
// Ausgabe (anders!):
// Lade...
// (1 Sekunde)
// Daten: { id: 1, name: "Max" }
// Weiter...
Häufige asynchrone Operationen
Timer
// Nach Zeit ausführen
setTimeout(() => {
console.log("Nach 1 Sekunde");
}, 1000);
// Wiederholt ausführen
const intervalId = setInterval(() => {
console.log("Alle 2 Sekunden");
}, 2000);
// Stoppen
clearInterval(intervalId);
Netzwerk-Anfragen (fetch)
// fetch ist asynchron!
fetch("https://api.example.com/users")
.then(response => response.json())
.then(users => console.log(users));
console.log("Fetch gestartet");
// Ausgabe:
// Fetch gestartet
// (irgendwann später)
// [User-Daten]
Event Listener
// Events sind asynchron - wir wissen nicht WANN geklickt wird
button.addEventListener("click", () => {
console.log("Irgendwann geklickt!");
});
console.log("Listener registriert");
// Ausgabe:
// Listener registriert
// (Klick passiert)
// Irgendwann geklickt!
Das Problem verstehen
Rückgabewert von asynchronem Code
// Das funktioniert NICHT wie erwartet!
function holeDaten() {
let ergebnis;
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => {
ergebnis = data;
});
return ergebnis; // undefined! Fetch ist noch nicht fertig!
}
const daten = holeDaten();
console.log(daten); // undefined
Die Lösung: Promise zurückgeben
// Richtig: Promise zurückgeben
function holeDaten() {
return fetch("https://api.example.com/data")
.then(response => response.json());
}
holeDaten().then(daten => {
console.log(daten); // Jetzt haben wir die Daten!
});
Synchron vs. Asynchron - Vergleich
| Aspekt | Synchron | Asynchron |
|---|---|---|
| Ausführung | Blockierend | Nicht blockierend |
| Reihenfolge | Garantiert | Nicht garantiert |
| UI | Kann einfrieren | Bleibt responsive |
| Fehlerhandling | try/catch | .catch() / try/catch mit await |
| Rückgabewert | Direkt | Promise |
Wann was verwenden?
Synchron
- Einfache Berechnungen
- String-Operationen
- Array-Manipulationen
- Alles was sofort fertig ist
// Synchron OK
const summe = zahlen.reduce((a, b) => a + b);
const gross = text.toUpperCase();
const filtered = array.filter(x => x > 10);
Asynchron
- Netzwerk-Anfragen (fetch, AJAX)
- Datei-Operationen
- Timer
- Datenbank-Abfragen
- Alles was “warten” erfordert
// Muss asynchron sein
const response = await fetch(url);
await writeFile(path, content);
await delay(1000);
const user = await database.getUser(id);
Zusammenfassung
// Synchron - blockiert, garantierte Reihenfolge
console.log("A");
console.log("B");
// Ausgabe: A, B
// Asynchron - blockiert nicht, Reihenfolge unsicher
console.log("A");
setTimeout(() => console.log("B"), 0);
console.log("C");
// Ausgabe: A, C, B
// Merksatz:
// - Synchron = sofort, der Reihe nach
// - Asynchron = später, wenn fertig
Der Weg zu modernem Code
Callbacks → Promises → async/await
| | |
V V V
"Callback "Besser "Sieht aus
Hell" lesbar" wie synchron"
In den nächsten Tutorials lernst du Promises und async/await im Detail!
Übung: Was ist die Ausgabe dieses Codes? Überlege erst, dann teste!
console.log("Start");
setTimeout(() => console.log("Timeout 1"), 0);
setTimeout(() => console.log("Timeout 2"), 0);
Promise.resolve().then(() => console.log("Promise 1"));
Promise.resolve().then(() => console.log("Promise 2"));
console.log("Ende");