189 lines
7.6 KiB
HTML
189 lines
7.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>JS 06: Async/Await & 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 & 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 & .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 & 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 & 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 & 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;">← 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 →</a>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|