Skip to content

Kapitel 12: async / await (Asynchrone Programmierung)

12.1 Was sind async / await?

📦 async / await Grundlagen

async / await ist die modernste und eleganteste Art, asynchronen Code in JavaScript zu schreiben (eingeführt in ES2017 / ES8).

SchlüsselwortBedeutung
asyncMarkiert eine Funktion als asynchron (gibt immer ein Promise zurück)
awaitPausiert die Ausführung, bis das Promise aufgelöst wird (nur in async Funktionen erlaubt)

🎯 Einfaches Beispiel

javascript
// Syntax
async function funktion() {
  const ergebnis = await promise;
  return ergebnis;
}

📝 Beispiel: Promise vs async/await

javascript
// ❌ Mit Promise
function getUser() {
  fetch("https://api.example.com/user/1")
    .then(response => response.json())
    .then(user => console.log(user))
    .catch(error => console.error(error));
}

// ✅ Mit async/await
async function getUser() {
  try {
    const response = await fetch("https://api.example.com/user/1");
    const user = await response.json();
    console.log(user);
  } catch (error) {
    console.error(error);
  }
}

Vorteile:

  • ✅ Sieht aus wie synchroner Code (einfacher zu lesen)
  • Fehlerbehandlung mit try/catch (wie bei synchronem Code)
  • Keine Callback-Verschachtelung

12.2 Grundlagen

🔤 async Funktion

Eine async Funktion gibt immer ein Promise zurück.

javascript
async function greet() {
  return "Hallo!";
}

// Gleichbedeutend mit:
function greet() {
  return Promise.resolve("Hallo!");
}

// Verwenden:
greet().then(result => console.log(result)); // "Hallo!"

🔤 await Ausdruck

await pausiert die Ausführung der async Funktion, bis das Promise aufgelöst wird.

javascript
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log("Start");
  await delay(1000);  // 1 Sekunde warten
  console.log("1 Sekunde spater");
}

demo();
// Ausgabe:
// "Start"
// (1 Sekunde warten)
// "1 Sekunde spater"

⚠️ Wichtig: await nur in async Funktionen

javascript
// ❌ Falsch - await außerhalb von async Funktion
function wrong() {
  const result = await somePromise;  // ❌ SyntaxError
}

// ✅ Richtig - in async Funktion
async function correct() {
  const result = await somePromise;  // ✅
}

12.3 Fehlerbehandlung

🔴 try...catch für Fehlerbehandlung

javascript
async function fetchUser() {
  try {
    const response = await fetch("https://api.example.com/user/999999");
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const user = await response.json();
    console.log(user);
  } catch (error) {
    console.error("Fehler beim Laden:", error);
  } finally {
    console.log("Bereinigung (immer ausgeführt)");
  }
}

fetchUser();

🔴 Fehler werfen mit throw

javascript
async function divide(a, b) {
  if (b === 0) {
    throw new Error("Division durch Null!");
  }
  return a / b;
}

async function demo() {
  try {
    const result = await divide(10, 0);
    console.log(result);
  } catch (error) {
    console.error(error.message);  // "Division durch Null!"
  }
}

demo();

🔴 Mehrere Fehlerquellen

javascript
async function fetchData() {
  try {
    const user = await fetchUser();      // Fehlerquelle 1
    const posts = await fetchPosts(user.id);  // Fehlerquelle 2
    const comments = await fetchComments(posts[0].id);  // Fehlerquelle 3
    
    return { user, posts, comments };
  } catch (error) {
    console.error("Fehler aufgetreten:", error);
    // Alle Fehler (von user, posts oder comments) werden hier abgefangen
  }
}

12.4 Kombination mit Promise

🔄 async / await gibt Promise zurück

javascript
async function add(a, b) {
  return a + b;
}

// Rückgabetyp ist immer Promise
const result = add(2, 3);
console.log(result);  // Promise { 5 }

// Deshalb:
add(2, 3).then(sum => console.log(sum));  // 5

🔄 await kann jedes Promise verwenden

javascript
// Eigene Promises
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log("Warte 1 Sekunde...");
  await delay(1000);
  console.log("Fertig!");
}

// Bereits existierende Promises (z.B. fetch)
async function fetchData() {
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();
  return data;
}

🔄 Parallele Ausführung mit Promise.all()

javascript
async function fetchAll() {
  try {
    // ❌ Sequenziell (langsam)
    // const user = await fetchUser();
    // const posts = await fetchPosts();
    
    // ✅ Parallel (schnell)
    const [user, posts, comments] = await Promise.all([
      fetchUser(),
      fetchPosts(),
      fetchComments()
    ]);
    
    return { user, posts, comments };
  } catch (error) {
    console.error("Ein Fehler ist aufgetreten:", error);
  }
}

🔄 Promise.race() mit async / await

javascript
async function fetchWithTimeout(url, timeout) {
  const fetchPromise = fetch(url);
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error("Timeout!")), timeout);
  });
  
  try {
    const response = await Promise.race([fetchPromise, timeoutPromise]);
    return response.json();
  } catch (error) {
    console.error(error.message);
  }
}

12.5 Praxis: Asynchrone Datenabfrage simulieren

🌐 Beispiel 1: Einfache Datenabfrage

javascript
// Datenabfrage simulieren
function fetchUser() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: 1, name: "Max Mustermann" });
    }, 1000);
  });
}

async function displayUser() {
  try {
    console.log("Lade Benutzer...");
    const user = await fetchUser();
    console.log(`Benutzer geladen: ${user.name}`);
  } catch (error) {
    console.error("Fehler:", error);
  }
}

displayUser();
// Ausgabe:
// "Lade Benutzer..."
// (1 Sekunde warten)
// "Benutzer geladen: Max Mustermann"

🌐 Beispiel 2: Verkettete Abfragen

javascript
function fetchUser() {
  return new Promise(resolve => {
    setTimeout(() => resolve({ id: 1, name: "Max" }), 500);
  });
}

function fetchPosts(userId) {
  return new Promise(resolve => {
    setTimeout(() => resolve([
      { id: 101, title: "Erster Post" },
      { id: 102, title: "Zweiter Post" }
    ]), 500);
  });
}

async function showUserAndPosts() {
  try {
    const user = await fetchUser();
    console.log("Benutzer:", user.name);
    
    const posts = await fetchPosts(user.id);
    console.log("Anzahl Posts:", posts.length);
    
    posts.forEach(post => {
      console.log("- " + post.title);
    });
  } catch (error) {
    console.error("Fehler:", error);
  }
}

showUserAndPosts();

🌐 Beispiel 3: Fehlerbehandlung in der Praxis

javascript
function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (url.includes("error")) {
        reject(new Error("Netzwerkfehler"));
      } else {
        resolve({ data: "Erfolgreich geladen" });
      }
    }, 1000);
  });
}

async function loadData() {
  try {
    const result = await fetchData("https://api.example.com/data");
    console.log(result.data);
  } catch (error) {
    console.error("Fehler aufgetreten:", error.message);
    
    // Fallback-Daten
    console.log("Verwende Fallback-Daten...");
    return { data: "Fallback-Daten" };
  }
}

loadData();

🌐 Beispiel 4: Parallele Abfragen in der Praxis

javascript
function fetchUser() {
  return new Promise(resolve => {
    setTimeout(() => resolve({ id: 1, name: "Max" }), 800);
  });
}

function fetchPosts() {
  return new Promise(resolve => {
    setTimeout(() => resolve([{ title: "Post 1" }, { title: "Post 2" }]), 600);
  });
}

function fetchComments() {
  return new Promise(resolve => {
    setTimeout(() => resolve([{ text: "Kommentar 1" }]), 1200);
  });
}

async function loadDashboard() {
  console.log("Lade Dashboard...");
  
  try {
    const [user, posts, comments] = await Promise.all([
      fetchUser(),
      fetchPosts(),
      fetchComments()
    ]);
    
    console.log("Dashboard geladen!");
    console.log("Benutzer:", user.name);
    console.log("Posts:", posts.length);
    console.log("Kommentare:", comments.length);
  } catch (error) {
    console.error("Fehler beim Laden des Dashboards:", error);
  }
}

loadDashboard();

🎉 Zusammenfassung

In diesem Kapitel hast du gelernt:

  • ✅ Was async / await sind (modernste asynchrone Programmierung)
  • async Funktionen (geben immer Promise zurück)
  • await Ausdrücke (pausieren die Ausführung)
  • ✅ Fehlerbehandlung mit try...catch
  • ✅ Kombination mit Promise (Promise.all(), Promise.race())
  • ✅ Praxisanwendungen (Datenabfrage simulieren)

📝 Übung

  1. Einfache async Funktion:

    javascript
    // Schreibe eine async Funktion 'greet', die "Hallo!" zurückgibt
  2. Fehlerbehandlung:

    javascript
    // Schreibe eine async Funktion 'divide(a, b)', die bei b=0 einen Fehler wirft
  3. Parallele Abfragen:

    javascript
    // Verwende Promise.all(), um 3 Funktionen parallel auszuführen

➡️ Nächstes Kapitel

In Kapitel 13 lernen wir Klassen (Class) - object-orientierte Programmierung in ES6!

Frei für alle Anfänger