Aufgaben-Python/courses/javascript/12_async_await_und_fetch/index.html
Alex Mueller 2571cb8847 feat(ux): responsive kurs-sidebar und kapitel-drawer für alle 13 kurse & web-ide
- Dynamic Sidebar mit window.COURSES_MANIFEST für 13 Kurse (216 Kapitel)
- Kurswechsler Dropdown mit Direktnavigation
- Fortschrittsanzeige mit Solved-Checkmarks (✓) aus localStorage
- Responsive Off-Canvas Drawer mit Floating Action Button (☰ Kapitel) & Backdrop auf Mobile/Tablets
- Web-IDE Topbar Drawer-Button (☰ Kapitel) für unterbrechungsfreien Vollbild-Editor
- Saubere Bereinigung redundanter statischer Legacy-Sidebars
2026-09-12 13:49:46 +02:00

192 lines
7.8 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<link rel="icon" type="image/svg+xml" href="../../../assets/favicon.svg">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS 06: Async/Await &amp; REST-APIs (Fetch)</title>
<link rel="stylesheet" href="../../../assets/style.css">
<style>
.comparison-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
margin: 20px 0;
}
.comparison-col {
background: var(--bg-surface);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
padding: 16px;
}
.comparison-col h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 1.05rem;
}
.analogy-box {
background: linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%);
border-left: 4px solid var(--primary);
border-radius: var(--radius-sm);
padding: 18px 20px;
margin: 18px 0;
}
.api-step {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 12px;
padding: 10px 14px;
background: var(--bg-subtle);
border-radius: var(--radius-sm);
}
.api-step-badge {
background: var(--primary);
color: white;
font-weight: 800;
font-size: 0.8rem;
padding: 2px 8px;
border-radius: var(--radius-full);
flex-shrink: 0;
}
</style>
</head>
<body>
<div class="app-layout">
<div class="app-main">
<header>
<div class="header-container">
<div class="header-badge">🌐 Modernes JavaScript</div>
<h1>JS 06: Async/Await &amp; REST-APIs (Fetch)</h1>
<p>Schreibe asynchronen Code so lesbar und linear wie synchronen Code mit <code>async</code>, <code>await</code> und <code>try/catch</code>.</p>
</div>
</header>
<main class="container">
<!-- Abschnitt 1: Konzept & Buch-Analogie -->
<section class="card">
<h2>📖 1. Warum Async/Await?</h2>
<p>
Mit <code>async/await</code> (ES2017) gehört unübersichtliches Promise-Chaining der Vergangenheit an. Asynchroner Code liest sich nun von oben nach unten wie ganz normaler, synchroner Code.
</p>
<div class="analogy-box">
<h3>📚 Die Buch-Lese-Analogie</h3>
<p>
<strong>Vorher (Callbacks &amp; .then()):</strong> Wie ein Buch, bei dem jedes Kapitel auf Fußnoten verweist (<em>„Lies auf Seite 80 weiter, um die Antwort zu finden“</em>).
</p>
<p style="margin-bottom: 0;">
<strong>Jetzt (Async/Await):</strong> Du liest das Buch ganz entspannt <strong>Zeile für Zeile von oben nach unten</strong>. Bei <code>await</code> pausiert der Erzähler kurz, holt die Information ab und liest genau an der Stelle flüssig weiter!
</p>
</div>
</section>
<!-- Abschnitt 2: Direktvergleich -->
<section class="card">
<h2>⚖️ 2. Gegenüberstellung: Promises vs. Async/Await</h2>
<div class="comparison-grid">
<div class="comparison-col">
<h3 style="color: #64748b;">⏳ Früher: Promise .then() Chaining</h3>
<pre><code>function ladeProfil(id) {
fetch(`/api/user/${id}`)
.then(res => {
if (!res.ok) throw new Error("404");
return res.json();
})
.then(user => {
console.log("Name:", user.name);
})
.catch(err => {
console.error("Fehler:", err);
});
}</code></pre>
</div>
<div class="comparison-col" style="border-color: var(--primary);">
<h3 style="color: var(--primary);">✨ Heute: Modernes Async/Await</h3>
<pre><code>async function ladeProfil(id) {
try {
const res = await fetch(`/api/user/${id}`);
if (!res.ok) throw new Error("404");
const user = await res.json();
console.log("Name:", user.name);
} catch (err) {
console.error("Fehler:", err);
}
}</code></pre>
</div>
</div>
</section>
<!-- Abschnitt 3: REST-APIs & Fetch-Muster -->
<section class="card">
<h2>🌐 3. REST-APIs konsumieren</h2>
<p>Typischer 2-Schritt-Ablauf beim Abrufen einer JSON-REST-API:</p>
<div class="api-step">
<span class="api-step-badge">Schritt 1</span>
<div>
<strong>HTTP-Request senden &amp; Statuscode prüfen:</strong>
<p style="margin: 4px 0 0 0; font-size: 0.9rem;">
<code>const res = await fetch(url);</code><br>
<code>if (!res.ok) throw new Error(`HTTP-Fehler: ${res.status}`);</code>
</p>
</div>
</div>
<div class="api-step">
<span class="api-step-badge">Schritt 2</span>
<div>
<strong>JSON-Body asynchron auslesen:</strong>
<p style="margin: 4px 0 0 0; font-size: 0.9rem;">
<code>const daten = await res.json();</code>
</p>
</div>
</div>
</section>
<!-- Abschnitt 4: Aufgaben & Checkliste -->
<section class="card">
<h2>🎯 Aufgaben &amp; Checkliste (Subgoals)</h2>
<div class="task-item">
<input type="checkbox" class="task-checkbox" id="t1">
<label class="task-label" for="t1">
<strong>TODO 1:</strong> <code>holeWetterDaten(stadtName, mockApiFetcher)</code> mit <code>await</code>, <code>res.ok</code>-Prüfung und <code>res.json()</code> implementieren.
</label>
</div>
<div class="task-item">
<input type="checkbox" class="task-checkbox" id="t2">
<label class="task-label" for="t2">
<strong>TODO 2:</strong> <code>aggregiereBenutzerPosts(userId, mockPostApiFetcher)</code> schreiben und Beitragsdaten aggregieren.
</label>
</div>
<div class="task-item">
<input type="checkbox" class="task-checkbox" id="t3">
<label class="task-label" for="t3">
<strong>TODO 3:</strong> <code>sichererApiAufruf(apiPromiseOderFn, standardFallback)</code> mit <code>try { ... } catch</code> absichern.
</label>
</div>
<!-- Lösungstipps Collapsible -->
<details style="margin-top: 20px; padding: 14px; background: #f8fafc; border: 1px solid var(--border-color); border-radius: var(--radius-sm);">
<summary style="cursor: pointer; font-weight: 700; color: var(--primary);">💡 Lösungstipps &amp; Hilfestellung</summary>
<ul style="margin-top: 10px; margin-left: 20px; font-size: 0.92rem; color: var(--text-body);">
<li>Deklariere jede asynchrone Funktion mit <code>async function ...</code>.</li>
<li>Prüfe vor <code>await res.json()</code> immer mit <code>if (!res.ok)</code> auf HTTP-Fehler.</li>
<li>Im <code>try / catch</code>-Block fängst du fehlgeschlagene Promises sauber ab und lieferst den Fallback-Wert.</li>
</ul>
</details>
<div style="margin-top: 24px; display: flex; gap: 12px; flex-wrap: wrap;">
<a href="../11_callbacks_und_promises/index.html" class="btn" style="background: #64748b; color: #fff; font-weight: 600; text-decoration: none; padding: 10px 20px; border-radius: 6px;">&larr; Zurück zu Modul 05</a>
<a href="../../../workspace.html?course=javascript&track=track_2_async_und_apis&chapter=06_async_await_und_fetch" class="btn" style="background: #eab308; color: #000; font-weight: 700; text-decoration: none; padding: 10px 20px; border-radius: 6px;">💻 In Web-IDE öffnen &rarr;</a>
</div>
</section>
</main>
</div>
</div>
<script src="../../../assets/courses_manifest.js"></script>
<script src="../../../assets/course_sidebar.js"></script>
</body>
</html>