Async und Await

Geschätzte Lektüre: 7 Minuten 321 Ansichten

Einführung in asynchrone Programmierung

Bevor wir zu async und await kommen, müssen wir verstehen, warum sie existieren. JavaScript ist single-threaded, was bedeutet, dass es nur eine Sache gleichzeitig tun kann. Lange Operationen (wie Netzwerkanfragen oder Dateizugriffe) würden den Hauptthread blockieren und die Anwendung einfrieren lassen.

Um dies zu vermeiden, verwendet JavaScript asynchrone Operationen mit Callbacks, Promises und schließlich async/await.

Von Callbacks zu Promises zu Async/Await

Callbacks: Die ursprüngliche Methode für asynchrone Operationen

function fetchData(callback) {
  setTimeout(() => {
    callback('Daten geladen');
  }, 1000);
}

fetchData((data) => {
  console.log(data); // "Daten geladen" nach 1 Sekunde
});

Promises: Eine bessere Struktur für asynchrone Operationen

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Daten geladen');
    }, 1000);
  });
}

fetchData().then(data => {
  console.log(data); // "Daten geladen" nach 1 Sekunde
});

Async/Await: Syntaktischer Zucker über Promises, der asynchronen Code wie synchronen aussehen lässt

Async-Funktionen

Eine async Funktion ist eine Funktion, die ein Promise zurückgibt. Wenn die Funktion einen Wert zurückgibt, wird das Promise mit diesem Wert aufgelöst. Wenn sie eine Exception wirft, wird das Promise mit diesem Fehler abgelehnt.

async function meineAsyncFunktion() {
  return 'Hallo';
}

// Äquivalent zu:
function meineAsyncFunktion() {
  return Promise.resolve('Hallo');
}

Beispiel:

async function begrüssen() {
  return 'Hallo Welt';
}

begrüssen().then(nachricht => console.log(nachricht)); // "Hallo Welt"

Await

Das await Schlüsselwort kann nur innerhalb einer async Funktion verwendet werden. Es pausiert die Ausführung der async-Funktion und wartet auf die Auflösung des übergebenen Promises. Dann wird die Ausführung fortgesetzt und der aufgelöste Wert wird zurückgegeben.

async function beispiel() {
  const wert = await promise; // wartet auf das Promise
  console.log(wert);
}

• Beispiel mit Fetch API:

async function fetchUserData() {
  const response = await fetch('https://api.example.com/user');
  const data = await response.json();
  console.log(data);
  return data;
}

fetchUserData();

Fehlerbehandlung

Für die Fehlerbehandlung bei async/await können wir try/catch-Blöcke verwenden:

async function fetchMitFehlerbehandlung() {
  try {
    const response = await fetch('https://api.example.com/user');
    if (!response.ok) {
      throw new Error('Netzwerkantwort war nicht ok');
    }
    const data = await response.json();
    console.log(data);
    return data;
  } catch (error) {
    console.error('Fehler beim Fetch:', error);
    // Fehler weiterwerfen oder behandeln
  }
}

Parallele Ausführung

Manchmal möchten wir mehrere asynchrone Operationen parallel ausführen:

async function paralleleAusführung() {
  // Starte beide Promises parallel
  const promise1 = fetch('https://api.example.com/data1');
  const promise2 = fetch('https://api.example.com/data2');
  
  // Warte auf beide Ergebnisse
  const [ergebnis1, ergebnis2] = await Promise.all([promise1, promise2]);
  
  const data1 = await ergebnis1.json();
  const data2 = await ergebnis2.json();
  
  return { data1, data2 };
}

Praktische Beispiele

Beispiel 1: Sequenzielle Ausführung

async function sequentielleAufrufe() {
  const user = await fetch('/user');
  const posts = await fetch(`/posts/${user.id}`);
  const comments = await fetch(`/comments/${posts[0].id}`);
  console.log(comments);
}

Beispiel 2: Timeout mit Async/Await

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

async function countdown() {
  console.log('3');
  await warte(1000);
  console.log('2');
  await warte(1000);
  console.log('1');
  await warte(1000);
  console.log('Los!');
}

Beispiel 3: Komplexe Fehlerbehandlung

async function komplexesBeispiel() {
  try {
    const user = await fetchUser();
    if (!user.valid) {
      throw new Error('Ungültiger Benutzer');
    }
    const posts = await fetchPosts(user.id);
    return { user, posts };
  } catch (error) {
    if (error instanceof TypeError) {
      console.error('Netzwerkfehler:', error);
    } else {
      console.error('Anwendungsfehler:', error);
    }
    throw error; // Weiterwerfen für höhere Ebene
  }
}

Wichtige Punkte zu beachten

Async-Funktionen geben immer Promises zurück:

async function foo() { return 1; }
console.log(foo() instanceof Promise); // true

Await kann nur in Async-Funktionen verwendet werden:

function bar() {
  await foo(); // SyntaxError: await is only valid in async function
}

Top-Level Await (in modernen Umgebungen):
In Modulen können Sie await auf oberster Ebene verwenden:

const user = await fetchUser();
console.log(user);

Performance: Obwohl await den Code pausiert, blockiert es nicht den Hauptthread. Andere Ereignisse können weiter verarbeitet werden.

Wertvolles Werkzeug

  • async markiert eine Funktion als asynchron und lässt sie ein Promise zurückgeben
  • await pausiert die Ausführung der async-Funktion bis das Promise aufgelöst ist
  • Async/Await macht asynchronen Code lesbarer und wartbarer
  • Fehler können mit try/catch behandelt werden
  • Parallele Operationen können mit Promise.all() durchgeführt werden

Async/Await ist ein mächtiges Werkzeug, das die Arbeit mit asynchronem JavaScript-Code deutlich vereinfacht, besonders im Vergleich zu Callback-Hell oder komplexen Promise-Ketten.

Dieses Dokument teilen

Async und Await

Oder Link kopieren

INHALT

Abonnieren

×
Cancel