# Erstellen Sie eine Banking-App Teil 3: Methoden zum Abrufen und Verwenden von Daten Denken Sie an den Computer der Enterprise in Star Trek – wenn Captain Picard nach dem Status des Schiffs fragt, erscheinen die Informationen sofort, ohne dass die gesamte Benutzeroberfläche herunterfährt und sich neu aufbaut. Dieser nahtlose Informationsfluss ist genau das, was wir hier mit dynamischem Datenabruf aufbauen. Im Moment ist Ihre Banking-App wie eine gedruckte Zeitung – informativ, aber statisch. Wir werden sie in etwas verwandeln, das eher wie die Missionskontrolle bei der NASA ist, wo Daten kontinuierlich fließen und sich in Echtzeit aktualisieren, ohne den Arbeitsablauf des Nutzers zu unterbrechen. Sie lernen, wie Sie asynchron mit Servern kommunizieren, Daten verarbeiten, die zu unterschiedlichen Zeiten eintreffen, und rohe Informationen in etwas Bedeutungsvolles für Ihre Nutzer verwandeln. Das ist der Unterschied zwischen einer Demo und produktionsbereiter Software. ## ⚡ Was Sie in den nächsten 5 Minuten tun können **Schnellstart-Pfad für beschäftigte Entwickler** ```mermaid flowchart LR A[⚡ 5 Minuten] --> B[API-Server einrichten] B --> C[Test Abruf mit curl] C --> D[Login-Funktion erstellen] D --> E[Daten in Aktion sehen] ``` - **Minute 1-2**: Starten Sie Ihren API-Server (`cd api && npm start`) und testen Sie die Verbindung - **Minute 3**: Erstellen Sie eine grundlegende `getAccount()`-Funktion mit fetch - **Minute 4**: Verbinden Sie das Login-Formular mit `action="javascript:login()"` - **Minute 5**: Testen Sie das Login und beobachten Sie, wie Kontodaten in der Konsole erscheinen **Schnelltest-Befehle**: ```bash # Überprüfen, ob die API läuft curl http://localhost:5000/api # Testen des Abrufs von Kontodaten curl http://localhost:5000/api/accounts/test ``` **Warum das wichtig ist**: In 5 Minuten erleben Sie die Magie des asynchronen Datenabrufs, der jede moderne Webanwendung antreibt. Das ist die Grundlage, die Apps reaktionsschnell und lebendig wirken lässt. ## 🗺️ Ihre Lernreise durch datengetriebene Webanwendungen ```mermaid journey title Von statischen Seiten zu dynamischen Anwendungen section Die Entwicklung verstehen Traditionelle Seitenaktualisierungen: 3: You Vorteile von AJAX/SPA entdecken: 5: You Fetch API-Muster meistern: 7: You section Authentifizierung aufbauen Login-Funktionen erstellen: 4: You Asynchrone Operationen handhaben: 6: You Benutzersitzungen verwalten: 8: You section Dynamische UI-Aktualisierungen DOM-Manipulation lernen: 5: You Transaktionsanzeigen erstellen: 7: You Reaktionsfähige Dashboards erstellen: 9: You section Professionelle Muster Template-basierte Darstellung: 6: You Strategien zur Fehlerbehandlung: 7: You Leistungsoptimierung: 8: You ``` **Ihr Lernziel**: Am Ende dieser Lektion verstehen Sie, wie moderne Webanwendungen Daten dynamisch abrufen, verarbeiten und anzeigen, um die nahtlosen Benutzererlebnisse zu schaffen, die wir von professionellen Anwendungen erwarten. ## Vorbereitendes Quiz [Vorbereitendes Quiz](https://ff-quizzes.netlify.app/web/quiz/45) ### Voraussetzungen Bevor Sie mit dem Datenabruf beginnen, stellen Sie sicher, dass Sie diese Komponenten bereithalten: - **Vorherige Lektion**: Schließen Sie das [Login- und Registrierungsformular](../2-forms/README.md) ab – darauf bauen wir auf - **Lokaler Server**: Installieren Sie [Node.js](https://nodejs.org) und [starten Sie den Server-API](../api/README.md) zur Bereitstellung von Kontodaten - **API-Verbindung**: Testen Sie Ihre Serververbindung mit diesem Befehl: ```bash curl http://localhost:5000/api # Erwartete Antwort: "Bank API v1.0.0" ``` Dieser Schnelltest stellt sicher, dass alle Komponenten richtig kommunizieren: - Verifiziert, dass Node.js auf Ihrem System korrekt läuft - Bestätigt, dass Ihr API-Server aktiv und antwortfähig ist - Validiert, dass Ihre App den Server erreichen kann (wie Funkkontakt vor einer Mission prüfen) ## 🧠 Überblick über das Datenmanagement-Ökosystem ```mermaid mindmap root((Datenverwaltung)) Authentication Flow Anmeldevorgang Formularvalidierung Anmeldeinformationen Überprüfung Sitzungsverwaltung Benutzerzustand Globales Kontoobjekt Navigationsschutz Fehlerbehandlung API Communication Abrufmuster GET-Anfragen POST-Anfragen Fehlerantworten Datenformate JSON-Verarbeitung URL-Kodierung Antwortparsing Dynamic UI Updates DOM-Manipulation Sichere Textaktualisierungen Elementerstellung Vorlagenklonen Benutzererlebnis Echtzeitaktualisierungen Fehlermeldungen Ladezustände Security Considerations XSS-Vermeidung Verwendung von textContent Eingabesäuberung Sichere HTML-Erstellung CORS-Verarbeitung Cross-Origin-Anfragen Header-Konfiguration Entwicklungssetup ``` **Grundprinzip**: Moderne Webanwendungen sind Datenorchestrierungssysteme – sie koordinieren zwischen Benutzeroberflächen, Server-APIs und dem Sicherheitsmodell des Browsers, um nahtlose, reaktionsschnelle Erlebnisse zu schaffen. --- ## Verständnis des Datenabrufs in modernen Web-Apps Die Art und Weise, wie Webanwendungen Daten verarbeiten, hat sich in den letzten zwei Jahrzehnten dramatisch entwickelt. Dieses Verständnis hilft Ihnen zu schätzen, warum moderne Techniken wie AJAX und die Fetch API so mächtig sind und warum sie zu unverzichtbaren Werkzeugen für Webentwickler geworden sind. Lassen Sie uns erkunden, wie traditionelle Webseiten funktionierten im Vergleich zu den dynamischen, reaktionsschnellen Anwendungen, die wir heute bauen. ### Traditionelle Mehrseitenanwendungen (MPA) In den frühen Tagen des Webs war jeder Klick wie das Umschalten auf einem alten Fernseher – der Bildschirm wurde leer, dann wurde der neue Inhalt langsam geladen. Dies war die Realität bei frühen Webanwendungen, bei denen jede Interaktion bedeutete, die gesamte Seite komplett neu aufzubauen. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Klickt auf Link oder sendet Formular ab Browser->>Server: Fordert neue HTML-Seite an Note over Browser: Seite wird leer Server->>Browser: Gibt komplette HTML-Seite zurück Browser->>User: Zeigt neue Seite an (Blitz/Neuladen) ``` ![Aktualisierungsworkflow in einer Mehrseitenanwendung](../../../../translated_images/de/mpa.7f7375a1a2d4aa77.webp) **Warum sich dieser Ansatz schwerfällig anfühlte:** - Jeder Klick bedeutete, die gesamte Seite neu zu laden - Nutzer wurden mitten im Gedankenfluss durch diese lästigen Seitenflashes unterbrochen - Ihre Internetverbindung arbeitete übermäßig, da dieselben Kopf- und Fußzeilen immer wieder heruntergeladen wurden - Apps fühlten sich eher an wie das Durchklicken in einem Aktenschrank als wie Software ### Moderne Single-Page-Anwendungen (SPA) AJAX (Asynchronous JavaScript and XML) hat dieses Paradigma komplett verändert. Wie das modulare Design der Internationalen Raumstation, bei dem Astronauten einzelne Komponenten austauschen können, ohne die ganze Struktur neu zu bauen, erlaubt AJAX uns, spezifische Teile einer Webseite zu aktualisieren, ohne alles neu zu laden. Obwohl der Name XML erwähnt, verwenden wir heute meist JSON, aber das Grundprinzip bleibt: Nur das aktualisieren, was sich ändert. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Interagiert mit Seite Browser->>JavaScript: Löst Ereignis-Handler aus JavaScript->>Server: Ruft nur benötigte Daten ab Server->>JavaScript: Gibt JSON-Daten zurück JavaScript->>Browser: Aktualisiert spezifische Seitenelemente Browser->>User: Zeigt aktualisierten Inhalt (kein Neuladen) ``` ![Aktualisierungsworkflow in einer Single-Page-Anwendung](../../../../translated_images/de/spa.268ec73b41f992c2.webp) **Warum SPAs sich so viel besser anfühlen:** - Nur die tatsächlich geänderten Bereiche werden aktualisiert (clever, oder?) - Keine ruckartigen Unterbrechungen mehr – Ihre Nutzer bleiben im Flow - Weniger Daten werden übertragen, was schnellere Ladezeiten bedeutet - Alles wirkt flink und reaktionsschnell, wie die Apps auf Ihrem Smartphone ### Die Entwicklung zur modernen Fetch API Moderne Browser bieten die [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), die den älteren [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) ersetzt. Wie der Unterschied zwischen Telegrafbedienung und E-Mail-Nutzung verwendet die Fetch API Promises für saubereren asynchronen Code und verarbeitet JSON auf natürliche Weise. | Merkmal | XMLHttpRequest | Fetch API | |---------|----------------|-----------| | **Syntax** | Komplex, callback-basiert | Sauber, promise-basiert | | **JSON-Verarbeitung** | Manuelle Verarbeitung erforderlich | Eingebaute `.json()`-Methode | | **Fehlerbehandlung** | Begrenzte Fehlerinformationen | Umfangreiche Fehlerdetails | | **Moderne Unterstützung** | Kompatibilität mit alten Browsern | ES6+ Promises und async/await | > 💡 **Browser-Kompatibilität**: Gute Nachrichten – die Fetch API funktioniert in allen modernen Browsern! Wenn Sie an bestimmten Versionen interessiert sind, bietet [caniuse.com](https://caniuse.com/fetch) die vollständige Kompatibilitätsübersicht. > **Das Fazit:** - Funktioniert hervorragend in Chrome, Firefox, Safari und Edge (ganz einfach überall dort, wo Ihre Nutzer sind) - Nur Internet Explorer benötigt spezielle Unterstützung (und ehrlich gesagt, es ist Zeit, IE loszulassen) - Bereitet Sie bestens auf die eleganten async/await-Patterns vor, die wir später verwenden werden ### Implementierung von Nutzer-Login und Datenabruf Nun implementieren wir das Login-System, das Ihre Banking-App von einer statischen Anzeige zu einer funktionalen Anwendung macht. Wie bei den Authentifizierungsprotokollen in sicheren Militäranlagen verifizieren wir Nutzeranmeldeinformationen und gewähren dann Zugriff auf die spezifischen Daten. Wir bauen dies schrittweise auf, beginnend mit der Basisauthentifizierung und dann der Ergänzung um Datenabruffunktionen. #### Schritt 1: Erstellen der Login-Funktionsbasis Öffnen Sie Ihre `app.js` und fügen Sie eine neue `login`-Funktion hinzu. Diese verarbeitet den Nutzer-Authentifizierungsprozess: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **So funktioniert das im Detail:** - Das `async` Schlüsselwort sagt JavaScript „hey, diese Funktion könnte auf Dinge warten müssen“ - Wir greifen auf unser Formular der Seite zu (nichts Besonderes, einfach per ID) - Dann holen wir raus, was der Nutzer als Benutzernamen eingegeben hat - Ein cooler Trick: Sie können auf jedes Formularelement durch dessen `name`-Attribut zugreifen – keine extra getElementById-Aufrufe nötig! > 💡 **Formularzugriffsmuster**: Jede Formulareingabe kann über ihren Namen (festgelegt im HTML mit dem `name`-Attribut) als Eigenschaft des Formular-Elements angesprochen werden. Das sorgt für sauberen, lesbaren Code beim Abrufen der Formulardaten. #### Schritt 2: Erstellen der Konto-Datenabruf-Funktion Als Nächstes erstellen wir eine dedizierte Funktion, um Kontodaten vom Server abzurufen. Dieses Muster ist ähnlich wie bei Ihrer Registrierungsfunktion, konzentriert sich aber auf das Abrufen von Daten: ```javascript async function getAccount(user) { try { const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user)); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` **Was dieser Code leistet:** - **Verwendet** die moderne `fetch` API für asynchronen Datenabruf - **Erstellt** eine GET-Anfrage-URL mit dem Benutzernamen als Parameter - **Setzt** `encodeURIComponent()` ein, um Sonderzeichen in URLs sicher zu handhaben - **Konvertiert** die Antwort in JSON-Format für einfache Datenverarbeitung - **Behandelt** Fehler elegant, indem ein Fehlerobjekt zurückgegeben wird, anstatt abzustürzen > ⚠️ **Sicherheitshinweis**: Die Funktion `encodeURIComponent()` behandelt Sonderzeichen in URLs. Wie bei Kodierungssystemen in der Marine sorgt sie dafür, dass Ihre Nachricht genau so ankommt, wie vorgesehen, und verhindert, dass Zeichen wie "#" oder "&" fehlinterpretiert werden. > **Warum das wichtig ist:** - Verhindert, dass Sonderzeichen URLs zerstören - Schützt vor URL-Manipulationsangriffen - Stellt sicher, dass Ihr Server die vorgesehenen Daten erhält - Folgt sicheren Programmierpraktiken #### Verständnis von HTTP GET-Anfragen Hier etwas, was Sie vielleicht überrascht: Wenn Sie `fetch` ohne zusätzliche Optionen verwenden, erzeugt es automatisch eine [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET)-Anfrage. Das passt perfekt zu unserem Zweck – wir fragen den Server „hey, kann ich die Kontodaten dieses Nutzers sehen?“ Stellen Sie sich GET-Anfragen vor wie eine höfliche Bibliotheksanfrage, ein Buch auszuleihen – Sie bitten darum, etwas zu sehen, das bereits existiert. POST-Anfragen (wie bei der Registrierung) sind eher wie das Einreichen eines neuen Buches, das in die Sammlung aufgenommen werden soll. | GET-Anfrage | POST-Anfrage | |-------------|--------------| | **Zweck** | Vorhandene Daten abrufen | Neue Daten an den Server senden | | **Parameter** | In URL-Pfad/Abfragezeichenfolge | Im Anfragetext (Body) | | **Caching** | Kann von Browsern zwischengespeichert werden | Meist nicht zwischengespeichert | | **Sicherheit** | Sichtbar in URL/Logs | Versteckt im Anfragetext | ```mermaid sequenceDiagram participant B as Browser participant S as Server Note over B,S: GET-Anfrage (Datenabruf) B->>S: GET /api/accounts/test S-->>B: 200 OK + Kontodaten Note over B,S: POST-Anfrage (Datenübermittlung) B->>S: POST /api/accounts + Neue Kontodaten S-->>B: 201 Created + Bestätigung Note over B,S: Fehlerbehandlung B->>S: GET /api/accounts/nonexistent S-->>B: 404 Not Found + Fehlermeldung ``` #### Schritt 3: Alles zusammenführen Jetzt zum befriedigenden Teil – wir verbinden Ihre Kontodaten-Abruf-Funktion mit dem Login-Prozess. Hier fügt sich alles zusammen: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` Diese Funktion folgt einer klaren Abfolge: - Den Benutzernamen aus dem Formulareingabefeld extrahieren - Kontodaten vom Server für den Nutzer anfordern - Etwaige Fehler während des Prozesses behandeln - Kontodaten speichern und nach erfolgreichem Login zum Dashboard navigieren > 🎯 **Async/Await-Muster**: Da `getAccount` asynchron ist, verwenden wir das `await`-Schlüsselwort, um die Ausführung zu pausieren, bis der Server antwortet. Das verhindert, dass der Code mit undefinierten Daten weiterläuft. #### Schritt 4: Einen Speicherort für Ihre Daten schaffen Ihre App benötigt einen Ort, um die Kontoinformationen zu speichern, sobald sie geladen sind. Stellen Sie sich das wie das Kurzzeitgedächtnis Ihrer App vor – ein Platz, um die aktuellen Nutzerdaten griffbereit zu halten. Fügen Sie folgende Zeile ganz oben in Ihre `app.js` ein: ```javascript // Dies enthält die Kontodaten des aktuellen Benutzers let account = null; ``` **Warum wir das brauchen:** - Macht Kontodaten überall in der App zugänglich - Startet mit `null`, was bedeutet: „niemand ist eingeloggt“ - Wird aktualisiert, wenn jemand erfolgreich anmeldet oder sich registriert - Dient als einzige wahre Datenquelle – keine Verwirrung darüber, wer gerade eingeloggt ist #### Schritt 5: Formular verbinden Nun verbinden wir Ihre nagelneue Login-Funktion mit Ihrem HTML-Formular. Aktualisieren Sie das Formular-Tag so: ```html
``` **Was diese kleine Änderung bewirkt:** - Verhindert, dass das Formular seine Standardaktion „Seite neu laden“ ausführt - Ruft stattdessen Ihre benutzerdefinierte JavaScript-Funktion auf - Hält alles flüssig und spa-ähnlich - Gibt Ihnen die volle Kontrolle darüber, was beim Klick auf „Login“ passiert #### Schritt 6: Registrierungsfunktion erweitern Zur Konsistenz aktualisieren Sie Ihre `register`-Funktion ebenfalls, sodass sie Kontodaten speichert und zum Dashboard navigiert: ```javascript // Fügen Sie diese Zeilen am Ende Ihrer Registrierungsfunktion hinzu account = result; navigate('/dashboard'); ``` **Diese Verbesserung bietet:** - **Nahtlosen** Übergang von der Registrierung zum Dashboard - **Konsistentes** Nutzererlebnis bei Login und Registrierung - **Sofortigen** Zugriff auf Kontodaten nach erfolgreicher Registrierung #### Testen Sie Ihre Implementierung ```mermaid flowchart TD A[Benutzer gibt Zugangsdaten ein] --> B[Login-Funktion aufgerufen] B --> C[Kontodaten vom Server abrufen] C --> D{Daten erfolgreich empfangen?} D -->|Ja| E[Kontodaten global speichern] D -->|Nein| F[Fehlermeldung anzeigen] E --> G[Zum Dashboard navigieren] F --> H[Benutzer bleibt auf der Login-Seite] ``` **Zeit für den Praxistest:** 1. Legen Sie ein neues Konto an, um sicherzugehen, dass alles funktioniert 2. Versuchen Sie, sich mit diesen Daten einzuloggen 3. Werfen Sie einen Blick in die Browser-Konsole (F12), wenn etwas komisch erscheint 4. Überprüfen Sie, ob Sie nach erfolgreichem Login auf dem Dashboard landen Wenn etwas nicht funktioniert, keine Panik! Die meisten Probleme sind einfache Fehler wie Tippfehler oder vergessen, den API-Server zu starten. #### Ein kurzes Wort zur Cross-Origin-Magie Vielleicht fragen Sie sich: „Wie kommuniziert meine Web-App mit diesem API-Server, wenn sie auf unterschiedlichen Ports laufen?“ Gute Frage! Das ist etwas, worauf jeder Webentwickler früher oder später stößt. > 🔒 **Cross-Origin-Sicherheit**: Browser erzwingen eine „Same-Origin-Policy“, um unautorisierte Kommunikation zwischen verschiedenen Domains zu verhindern. Wie ein Kontrollpunkt im Pentagon prüfen sie, ob die Kommunikation erlaubt ist, bevor Daten übertragen werden. > **In unserem Setup:** - Läuft Ihre Web-App auf `localhost:3000` (Entwicklungsserver) - Läuft Ihr API-Server auf `localhost:5000` (Backend-Server) - Der API-Server enthält [CORS-Header](https://developer.mozilla.org/docs/Web/HTTP/CORS), die explizit die Kommunikation mit Ihrer Web-App erlauben Diese Konfiguration entspricht der realen Entwicklung, bei der Frontend- und Backend-Anwendungen meist auf getrennten Servern laufen. > 📚 **Mehr erfahren**: Tauchen Sie tiefer in APIs und Datenabruf ein mit diesem umfassenden [Microsoft Learn-Modul zu APIs](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Ihre Daten durch HTML zum Leben erwecken Jetzt machen wir die abgerufenen Daten für Nutzer über DOM-Manipulation sichtbar. Wie im analogen Fotolabor entwickeln wir unsichtbare Daten zu etwas, das Nutzer sehen und mit dem sie interagieren können. DOM-Manipulation ist die Technik, die statische Webseiten in dynamische Anwendungen verwandelt, die ihre Inhalte basierend auf Benutzerinteraktionen und Serverantworten aktualisieren. ### Die richtige Werkzeugwahl für den Job Wenn es darum geht, dein HTML mit JavaScript zu aktualisieren, hast du mehrere Optionen. Denk an diese wie verschiedene Werkzeuge in einem Werkzeugkasten – jedes perfekt für bestimmte Aufgaben: | Methode | Wofür sie großartig ist | Wann man sie benutzt | Sicherheitsstufe | |--------|-------------------------|---------------------|------------------| | `textContent` | Sichere Anzeige von Benutzerdaten | Immer wenn du Text anzeigen willst | ✅ Felsenfest | | `createElement()` + `append()` | Aufbau komplexer Layouts | Neue Abschnitte/Listen erstellen | ✅ Bombensicher | | `innerHTML` | Setzen von HTML-Inhalten | ⚠️ Versuche, diese Methode zu vermeiden | ❌ Risikohaft | #### Der sichere Weg, Text anzuzeigen: textContent Die [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent)-Eigenschaft ist dein bester Freund, wenn es darum geht, Benutzerdaten anzuzeigen. Es ist, als hättest du einen Türsteher für deine Webseite – nichts Gefährliches kommt durch: ```javascript // Der sichere, zuverlässige Weg, Text zu aktualisieren const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Vorteile von textContent:** - Behandelt alles als reinen Text (verhindert die Ausführung von Skripten) - Löscht automatisch vorhandenen Inhalt - Effizient für einfache Textupdates - Bietet integrierten Schutz gegen bösartigen Inhalt #### Dynamische HTML-Elemente erstellen Für komplexere Inhalte kombiniere [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) mit der [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append)-Methode: ```javascript // Sicherer Weg, um neue Elemente zu erstellen const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **So funktioniert dieser Ansatz:** - **Erstellt** DOM-Elemente programmgesteuert neu - **Behält** volle Kontrolle über Elementattribute und Inhalte - **Ermöglicht** komplexe, verschachtelte Elementstrukturen - **Bewahrt** die Sicherheit, indem Struktur von Inhalt getrennt wird > ⚠️ **Sicherheitsbedenken**: Obwohl [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) in vielen Tutorials auftaucht, kann es eingebettete Skripte ausführen. Wie die Sicherheitsprotokolle am CERN, die unbefugte Codeausführung verhindern, bieten `textContent` und `createElement` sicherere Alternativen. > **Risiken von innerHTML:** - Führt jegliche `