Begriff
Async/Await
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Früher blockierte Code: file.read(). Das Programm fror ein, bis die Festplatte fertig war.
Dann kamen Callbacks: file.read(() => { ... }). Führte zur "Callback Hell" (Verschachtelung des Grauens).
Async/Await (erfunden von C#, populär durch JS/Python/Rust) ist syntaktischer Zucker.
Du schreibst Code, der aussieht wie synchroner Code:
let content = await file.read();
Aber unter der Haube blockiert er nicht.
Wenn das await kommt, gibt die Funktion die Kontrolle ab.
Der Prozessor macht andere Dinge (UI zeichnen, andere Requests).
Wenn die Datei da ist, springt er zurück an diese Stelle.
Es macht asynchrone Programmierung lesbar.
Merksatz: Ein Sprachkonstrukt, das es ermöglicht, asynchronen (nicht-blockierenden) Code in einer synchronen, linearen Struktur zu schreiben, indem es Promises/Futures hinter den Schlüsselwörtern async und await verbirgt.
Fast überall.
- JavaScript:
async function fetchUser() { ... }. - Python:
async def main(): ...(mitasyncio). - Rust:
async fn run() { ... }(mittokio). Wichtig: "Async Viruses". Wenn eine Funktionasyncist, müssen alle, die sie aufrufen, auchasyncsein (oderawaitnutzen).
1. State Machines
Der Compiler wandelt eine async Funktion in eine State Machine um.
Jedes await ist ein Zustand.
State 1 -> (Warte auf IO) -> State 2.
In Rust passiert das ohne Heap-Allokation (Zero Cost).
In JS/Java entstehen Promise-Objekte auf dem Heap.
2. Cooperative Multitasking
Async ist kein Multithreading!
Alles läuft oft auf einem Thread (Event Loop).
Wenn du await heavyCalculation() machst, blockierst du trotzdem alles.
await hilft nur bei I/O (Warten auf externe Dinge). Für CPU-Last brauchst du Threads.
1. Futures, Promises und Polling
Unter der Haube von async/await liegt das Konzept des "Future" oder "Promise" (ein Wert, der in der Zukunft aufgelöst wird).
In JavaScript (Node.js) läuft das klassisch über die libuv Event Loop in C++. Promises sind dort "Hot" (eager): Die asynchrone Operation (z.B. ein DB-Call) startet in dem Moment, wo die Funktion aufgerufen wird, unabhängig vom await.
In Rust sind Futures jedoch "Cold" (lazy): Ein Future ist buchstäblich nur ein Struct (eine State Machine). Er tut absolut nichts, feuert keine Sockets ab, bis nicht ein Executor (wie Tokio) explizit poll() aufruft. Erst dieses Polling treibt die I/O Maschine voran, was massiven Performance-Gewinn bringt.
2. Colouring of Functions (What color is your function?)
Das größte architektonische Kritikproblem an async/await. Es teilt die Sprachendiagnostik in zwei Farben ein: Rote (async) und blaue (sync) Funktionen.
Eine blaue Funktion kann rot aufrufen, was aber zum Deadlock des Threads führen kann (Blocking). Eine rote Funktion kann alles. Wenn du tief unten in einem Legacy-Codebase einen winzigen HTTP-Call einbaust (der async ist), infiziert das den gesamten Call-Stack bis zur Main Methode, die nun ebenfalls async werden muss. Man nennt dies auch "Function Colouring"-Problem (inspiriert durch Bob Nystroms Essay).
3. Goroutines / Virtual Threads als Gegenkonzept
Go (Golang) und neuerdings Java (mit Projekt Loom / Virtual Threads) lehnen async/await kategorisch ab. Statt dem Entwickler das Jonglieren mit Keywords aufzubürden, lassen sie den Code "scheinbar" synchron aussehen. Im Hintergrund verwaltet die Laufzeitumgebung Millionen von ressourcenschonenden virtuellen Web-Threads. Wenn read() droht zu blockieren, stoppt die Go-Runtime die Goroutine transparent, swappt den Stack, und gibt dem Kern etwas anderes zu tun. Das Resultat: Keinen Promise-Overhead und perfekte Lesbarkeit.
Quick-Check
Fehlerbehandlung?
Einfachtry { await ... } catch (e) { ... }. Viel besser als.catch(err => ...)bei Promises.Deadlocks?
Möglich, aber seltener als bei Threads. Häufiger sind "Hangs", wenn man vergisst, ein Promise aufzulösen.Rust vs JS?
In JS startet das Promise sofort (Hot). In Rust sind Futures "Lazy". Sie tun nichts, bis man sie "pollt" (.await).