# Erstellen einer Banking-App Teil 3: Methoden zum Abrufen und Verwenden von Daten ## Quiz vor der Vorlesung [Quiz vor der Vorlesung](https://ff-quizzes.netlify.app/web/quiz/45) ### Einführung Im Kern jeder Webanwendung stehen *Daten*. Daten können viele Formen annehmen, aber ihr Hauptzweck ist es immer, dem Benutzer Informationen anzuzeigen. Da Webanwendungen zunehmend interaktiver und komplexer werden, ist die Art und Weise, wie der Benutzer auf Informationen zugreift und mit ihnen interagiert, ein zentraler Bestandteil der Webentwicklung. In dieser Lektion werden wir sehen, wie man Daten asynchron von einem Server abruft und diese Daten verwendet, um Informationen auf einer Webseite anzuzeigen, ohne das HTML neu zu laden. ### Voraussetzungen Für diese Lektion musst du den [Login- und Registrierungsformular](../2-forms/README.md)-Teil der Webanwendung erstellt haben. Außerdem musst du [Node.js](https://nodejs.org) installieren und die [Server-API](../api/README.md) lokal ausführen, um auf Kontodaten zuzugreifen. Du kannst testen, ob der Server ordnungsgemäß läuft, indem du diesen Befehl in einem Terminal ausführst: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX und Datenabruf Traditionelle Webseiten aktualisieren den angezeigten Inhalt, wenn der Benutzer einen Link auswählt oder Daten über ein Formular sendet, indem die gesamte HTML-Seite neu geladen wird. Jedes Mal, wenn neue Daten geladen werden müssen, liefert der Webserver eine komplett neue HTML-Seite, die vom Browser verarbeitet werden muss. Dies unterbricht die aktuelle Benutzeraktion und schränkt die Interaktionen während des Neuladens ein. Dieser Workflow wird auch als *Multi-Page Application* oder *MPA* bezeichnet.  Als Webanwendungen komplexer und interaktiver wurden, entstand eine neue Technik namens [AJAX (Asynchronous JavaScript and XML)](https://de.wikipedia.org/wiki/Ajax_(Programmierung)). Diese Technik ermöglicht es Webanwendungen, Daten asynchron von einem Server zu senden und abzurufen, ohne die HTML-Seite neu laden zu müssen. Das führt zu schnelleren Updates und flüssigeren Benutzerinteraktionen. Wenn neue Daten vom Server empfangen werden, kann die aktuelle HTML-Seite auch mit JavaScript über die [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)-API aktualisiert werden. Im Laufe der Zeit hat sich dieser Ansatz zu dem entwickelt, was heute als [*Single-Page Application* oder *SPA*](https://de.wikipedia.org/wiki/Single-Page-Webanwendung) bekannt ist.  Als AJAX erstmals eingeführt wurde, war die einzige verfügbare API zum asynchronen Abrufen von Daten [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Moderne Browser implementieren jedoch auch die bequemere und leistungsfähigere [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), die auf Promises basiert und besser geeignet ist, um JSON-Daten zu verarbeiten. > Obwohl alle modernen Browser die `Fetch API` unterstützen, solltest du, wenn deine Webanwendung auch auf älteren Browsern funktionieren soll, immer die [Kompatibilitätstabelle auf caniuse.com](https://caniuse.com/fetch) überprüfen. ### Aufgabe In [der vorherigen Lektion](../2-forms/README.md) haben wir das Registrierungsformular implementiert, um ein Konto zu erstellen. Jetzt fügen wir Code hinzu, um sich mit einem bestehenden Konto anzumelden und dessen Daten abzurufen. Öffne die Datei `app.js` und füge eine neue Funktion `login` hinzu: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Hier beginnen wir damit, das Formularelement mit `getElementById()` abzurufen, und holen dann den Benutzernamen aus dem Eingabefeld mit `loginForm.user.value`. Jedes Formularelement kann über seinen Namen (im HTML mit dem Attribut `name` festgelegt) als Eigenschaft des Formulars aufgerufen werden. Ähnlich wie bei der Registrierung erstellen wir eine weitere Funktion, um eine Serveranfrage auszuführen, diesmal jedoch, um die Kontodaten abzurufen: ```js 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' }; } } ``` Wir verwenden die `fetch` API, um die Daten asynchron vom Server anzufordern. Diesmal benötigen wir keine zusätzlichen Parameter außer der URL, da wir nur Daten abfragen. Standardmäßig erstellt `fetch` eine [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET)-HTTP-Anfrage, was hier genau das ist, was wir brauchen. ✅ `encodeURIComponent()` ist eine Funktion, die Sonderzeichen für URLs maskiert. Welche Probleme könnten auftreten, wenn wir diese Funktion nicht aufrufen und den Wert von `user` direkt in der URL verwenden? Jetzt aktualisieren wir unsere `login`-Funktion, um `getAccount` zu verwenden: ```js 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'); } ``` Da `getAccount` eine asynchrone Funktion ist, müssen wir sie mit dem Schlüsselwort `await` verwenden, um auf das Serverergebnis zu warten. Wie bei jeder Serveranfrage müssen wir auch Fehlerfälle behandeln. Für den Moment fügen wir nur eine Log-Nachricht hinzu, um den Fehler anzuzeigen, und kommen später darauf zurück. Dann müssen wir die Daten irgendwo speichern, damit wir sie später verwenden können, um die Dashboard-Informationen anzuzeigen. Da die Variable `account` noch nicht existiert, erstellen wir eine globale Variable dafür am Anfang unserer Datei: ```js let account = null; ``` Nachdem die Benutzerdaten in einer Variablen gespeichert wurden, können wir mit der Funktion `navigate()` von der *Login*-Seite zum *Dashboard* wechseln. Schließlich müssen wir unsere `login`-Funktion aufrufen, wenn das Login-Formular abgeschickt wird, indem wir das HTML ändern: ```html