From 9512c8190336d542d9ed5131ede8c4951b7b12ff Mon Sep 17 00:00:00 2001 From: Denis Ergin Date: Mon, 6 Jan 2025 09:46:41 +0100 Subject: [PATCH] feat(slides): data fetching --- .../08-data-fetching/fetch-demo.astro | 32 ++++++ .../javascript/08-data-fetching/headers.astro | 54 ++++++++++ .../javascript/08-data-fetching/index.astro | 15 +++ .../javascript/08-data-fetching/json.astro | 65 +++++++++++ .../08-data-fetching/make-a-request.astro | 53 +++++++++ .../08-data-fetching/response.astro | 102 ++++++++++++++++++ .../javascript/08-data-fetching/title.astro | 3 + .../slides/javascript/08-data-fetching.astro | 8 ++ 8 files changed, 332 insertions(+) create mode 100644 src/components/slides/javascript/08-data-fetching/fetch-demo.astro create mode 100644 src/components/slides/javascript/08-data-fetching/headers.astro create mode 100644 src/components/slides/javascript/08-data-fetching/index.astro create mode 100644 src/components/slides/javascript/08-data-fetching/json.astro create mode 100644 src/components/slides/javascript/08-data-fetching/make-a-request.astro create mode 100644 src/components/slides/javascript/08-data-fetching/response.astro create mode 100644 src/components/slides/javascript/08-data-fetching/title.astro create mode 100644 src/pages/slides/javascript/08-data-fetching.astro diff --git a/src/components/slides/javascript/08-data-fetching/fetch-demo.astro b/src/components/slides/javascript/08-data-fetching/fetch-demo.astro new file mode 100644 index 0000000..292fb86 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/fetch-demo.astro @@ -0,0 +1,32 @@ +--- +interface Props { + url: string, + id: string, + converter: 'text', +} + +const { url, id, converter } = Astro.props; +--- + +
+ + +
+ +
+ + +
\ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/headers.astro b/src/components/slides/javascript/08-data-fetching/headers.astro new file mode 100644 index 0000000..eb0e9d7 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/headers.astro @@ -0,0 +1,54 @@ +
+
+

Headers

+
+ +
+

Headers sind dafür zuständig zusätzliche Informationen vom und zum Server zu übertragen.

+

Diese Informationen sind unter anderem: Authentifizierungs und Authentifikations-Informationen, Caching-Informationen, Content-Flags, Cookies, Cross-Origin-Resource-Sharing-Informationen, und viele weitere.

+

Eine Umfangreiche Liste ist zu finden auf Developer Mozilla

+
+ +
+

Header sind eine spezielle Klasse die initiiert werden kann.

+

+      const headers = new Headers();
+
+      // Header können folgendermaßen in
+      // einem Request verwendet werden
+      const response = await fetch('url', {
+        headers,
+      });
+    
+
+ +
+

Die Header-Instanz enthält folgende Funktionen um Header zu modifizieren:

+
+ +
+

headers.append(name, value)

+

Fügt einen neuen Header-Eintrag zum Objekt hinzu

+
+ +
+

headers.delete(name)

+

Entfernt einen Eintrag aus dem Header

+
+ +
+

headers.get(name)

+

Gibt einen String zurück der den Inhalt des Angegebenen Header-Eintrages abbildet. null wenn kein Eintrag vorhanden ist.

+
+ +
+

headers.has(name)

+

Prüft ob ein Header-Eintrag mit gegebenen Namen existiert, falls ja liefert die Funktion true, andernfalls false.

+
+ +
+

headers.set(name, value)

+

Setzt einen Eintrag im Header-Objekt mit angegebenem Wert, überschreibt existierende Werte.

+

Zum Anhängen an einen existierenden Wert, kann man die Funktion .append() nutzen

+
+
\ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/index.astro b/src/components/slides/javascript/08-data-fetching/index.astro new file mode 100644 index 0000000..f4d5a58 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/index.astro @@ -0,0 +1,15 @@ +--- +import Title from "./title.astro"; +import MakeARequest from "./make-a-request.astro"; +import Json from "./json.astro"; +import Response from "./response.astro"; +import Headers from "./headers.astro"; +--- + +
+ + <MakeARequest /> + <Json /> + <Response /> + <Headers /> +</div> \ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/json.astro b/src/components/slides/javascript/08-data-fetching/json.astro new file mode 100644 index 0000000..961edf2 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/json.astro @@ -0,0 +1,65 @@ +<section> + <section> + <h2>JSON</h2> + <p>"Jason", oder auch "JavaScript Object Notation"</p> + </section> + + <section> + <p>JSON ist ein modernes Datenformat um strukturierte Daten zu übertragen.</p> + <p>Der Inhalt ist dabei stark den JavaScript-Objekten nachempfunden</p> + </section> + + <section> + <pre class="json"><code data-trim data-line-numbers is:raw style="max-height: 600px;"> + { + "days_until":38, + "following_production": { + "days_until":58, + "id":202555, + "overview":"Matt Murdock, a blind lawyer with heightened abilities, is fighting for justice through his bustling law firm, while former mob boss Wilson Fisk pursues his own political endeavors in New York. When their past identities begin to emerge, both men find themselves on an inevitable collision course.", + "poster_url":"https://image.tmdb.org/t/p/w500/bSsjWM91kSZqW0BagqaoIeo8Jz7.jpg", + "release_date":"2025-03-04", + "title":"Daredevil: Born Again", + "type":"TV Show" + }, + "id":822119, + "overview":"After meeting with newly elected U.S. President Thaddeus Ross, Sam finds himself in the middle of an international incident. He must discover the reason behind a nefarious global plot before the true mastermind has the entire world seeing red.", + "poster_url":"https://image.tmdb.org/t/p/w500/z0ujnXounP4yq637zyLBiZThF7Y.jpg", + "release_date":"2025-02-12", + "title":"Captain America: Brave New World", + "type":"Movie" + } + </code></pre> + </section> + + <section> + <p>Es sind alle Gängigen JavaScript Datentypen erlaubt, inklusive <code>null</code> und <code>undefined</code>.</p> + <p>Es gibt per-se keine Feste Datenstruktur, die vorgibt welche keys erlaubt sind und welche nicht. Wir können das Datenformat entsprechend dynamisch gestalten.</p> + </section> + + <section> + <p>Es gibt aber darauf aufbauend das JSON-Schema, mit dem ein Parser eine "wohlgeformte" JSON-Struktur identifizieren kann.</p> + <p>JSON-Schema ist aber nicht teil dieser Vorlesung.</p> + </section> + + <section> + <p>"Vorgänger" von JSON ist / war SOAP. SOAP war XML-Basiert und wurde früher in großem Umfang von vielen Systemen benutzt. Aufgrund des Aufwandes ist aber JSON nun der de-facto Standard bei Datenübertragungen.</p> + <p>Alle modernen Programmiersprachen bieten Optionen, JSON in Strukturierte Klassen zu parsen.</p> + <p>Und selbst in JavaScript müssen wir "rohes" JSON in geparste Objekte übersetzten.</p> + </section> + + <section> + <p>Hierfür steht uns das globale Objekt <code>JSON</code> mit den Funktionen <code>stringify & parse</code> zur Verfügung</p> + <pre class="js"><code data-trim data-line-numbers is:raw> + const myObject = { value: 42 }; + + const asString = JSON.stringify(myObject); + + console.log(asString); + + const parsed = JSON.parse(asString); + + console.log(parsed); + </code></pre> + </section> +</section> \ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/make-a-request.astro b/src/components/slides/javascript/08-data-fetching/make-a-request.astro new file mode 100644 index 0000000..e3fbdf2 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/make-a-request.astro @@ -0,0 +1,53 @@ +--- +import FetchDemo from "./fetch-demo.astro"; +--- + +<section> + <section> + <h2>Requests & Fetch API</h2> + </section> + + <section> + <p>Ein Disclaimer: Wir werden im Rahmen der Vorlesung mit der moderneren <code>fetch</code> API arbeiten. Die Fetch-API hat <code>XMLHttpRequest</code> abgelöst und bietet moderne Features.</p> + </section> + + <!-- https://www.whenisthenextmcufilm.com/api --> + + <section> + <p>Anatomie eines Fetch-Aufrufs</p> + <p>Zu Demonstrations-Zwecken nutzen wir eine offene API, die wir ansteuern können:</p> + <pre class="js"><code data-trim data-line-numbers is:raw> + // Eine offene API zum abfragen einfacher Wetter-Daten + const url = 'https://wttr.in/Karlsruhe?format=4'; + + // Fetch gibt uns ein Promise + // erfolgreich wenn Request erfolgreich + const response = await fetch(url); + + // als letzter schritt holen wir die daten mittels .text() + console.log(await response.text()); + </code></pre> + + <FetchDemo converter="text" url="https://wttr.in/Karlsruhe?format=4" id="wttr-demo-1" /> + </section> + + <section> + <p>Wenn wir nichts weiter als die URL angeben, wird ein <code>GET</code> Request ausgeführt.</p> + <p>Die verschiedenen Request-Formate haben wir bereits betrachtet.</p> + <p>Weiterhin können wir erkennen, dass ein fetch-Aufruf ein Promise zurück gibt, dass wir <code>await</code>'en müsen</p> + </section> + + <section> + <h3>Fetch-Optionen</h3> + </section> + + <section> + <p>Wenn wir z.B. POST Requests machen wollen, müssen wir zusätzliche Optionen als 2. Parameter mitgeben</p> + <pre class="js"><code data-trim data-line-numbers is:raw> + fetch("url", { + method: "POST", // "PUT", "DELETE" + body: "Inhalt", + }); + </code></pre> + </section> +</section> \ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/response.astro b/src/components/slides/javascript/08-data-fetching/response.astro new file mode 100644 index 0000000..bf194e3 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/response.astro @@ -0,0 +1,102 @@ +<section> + <section> + <h2>Responses</h2> + </section> + + <section> + <p>Wir haben unseren Request abgeschickt und haben eine Antwort erhalten.</p> + <p>In den Folien vorher haben wir auch die Antwort bereits extrahiert und angezeigt.</p> + <p>Bisher haben wir aber nur die Funktion <code>await response.text()</code> verwendet. Sie liefert den Inhalt der Antwort als normalen String zurück.</p> + </section> + + <section> + <p>Falls es euch damals aufgefallen ist, haben wir beim Empfang des Inhalts mittels <code>.text()</code> die Antwort mit <code>await</code> abwarten mussten.</p> + <p>Die Funktion liefert also ein Promise das mit dem Inhalt der Antwort des Requests zurück kommt.</p> + <p>Aber warum?</p> + </section> + + <section> + <p>Das liegt daran wie die Datenübertragung funktioniert.</p> + <p>In dem Moment in dem der Request-Promise "erfüllt" ist, haben wir zwangsweise noch keine Daten erhalten.</p> + <p>Die Daten vom Body werden als Stream gespeichert. Solange die Datenübertragung noch nicht abgeschlossen ist wird der Stream weiter gefüllt.</p> + <p>Die Abfrage der Inhalte vom Body mittels <code>.text()</code> erwartet also, dass der Stream vollständig ist.</p> + </section> + + <section> + <p>Blicken wir aber noch genauer auf den Zustand zwischen dem Request Promise und dem Aufruf um Inhalte zu erhalten.</p> + </section> + + <section> + <p>Wenn wir vom Server eine Antwort erhalten, kommen die Header zuerst im Browser an.</p> + <p>Im Header stehen alle für den Request Relevanten Meta-Informationen.</p> + <p>Unter anderem ist dort auch der HTTP-Status-Code enthalten, mit dem wir den Erfolg des Requests bestimmen können.</p> + </section> + + <section> + <p>HTTP-Statuscodes sind eine 3-Stellige Nummer zwischen 100 und 599.</p> + <p>Jede Nummer steht für eine andere Art von Antwort. Grob Kategorisiert werden diese im Hunderter-Bereich:</p> + <ol> + <li>100er > "Informative" Antworten</li> + <li>200er > Erfolgreiche Antworten</li> + <li>300er > Umleitungen / Redirects</li> + <li>400er > Client-Fehler</li> + <li>500er > Server-Fehler</li> + </ol> + </section> + + <section> + <p>Die am gebräuchlichsten Antworten sind:</p> + <p>200 > OK, 201 > Created, 204 > No Content, 301 > Moved Permanently, 304 > Not Modified, 400 > Bad Request, 401 > Unauthorized, 403 > Forbidden, 404 > Not Found, 500 > Internal Server Error</p> + <p>Für eine komplette Liste, kann man das Internet fragen, z.B. <a href="https://http.cat" target="_blank" rel="noopener noreferrer">HTTP Cats</a></p> + </section> + + <section> + <p>Zurück zur Response: Wir erhalten also in den Headern bereits den Erfolg oder Miserfolg des Requests, bevor die Daten angekommen sind.</p> + <p>Entsprechend wird der Request-Promise fullfiled, bevor die Daten komplett angekommen sind.</p> + <p>Deswegen ist <code>.text()</code> ein Promise, wir warten noch auf die Vollständigkeit der Daten.</p> + </section> + + <section> + <p>Das Response Objekt hat aber noch weitere Informationen und Funktionen.</p> + </section> + + <section> + <p>response.headers</p> + <p>In der headers-property sind alle in der Response beinhalteten Header aufgelistet. </p> + </section> + + <section> + <p>response.ok</p> + <p><code>true</code>, wenn der HTTP-Statuscode im Bereich 200 bis 299 liegt.</p> + </section> + + <section> + <p>response.status</p> + <p>Der HTTP-Statuscode den der Server übermittelt hat.</p> + </section> + + <section> + <p>response.statusText</p> + <p>Eine Beschreibung des Response-Codes (z.B. OK für 200)</p> + </section> + + <section> + <p>response.text() (Promise)</p> + <p>Extrahiert die Antwort des Servers als "Plain-Text"</p> + </section> + + <section> + <p>response.json() (Promise)</p> + <p>Extrahiert die Antwort des Servers als JSON-Struktur und parsed die sofort in ein JavaScript-Objekt um.</p> + </section> + + <section> + <p>Weitere Extraktoren:</p> + <ul> + <li>.formData() zur Extraktion der Antwort als FormData Objekt</li> + <li>.blob() zur Extraktion der Antwort als Blob</li> + <li>.arrayBuffer() zur Extraktion der Antwort als ArrayBuffer</li> + <li>.bytes() zur Extraktion der Antwort in ein Uint8Array</li> + </ul> + </section> +</section> \ No newline at end of file diff --git a/src/components/slides/javascript/08-data-fetching/title.astro b/src/components/slides/javascript/08-data-fetching/title.astro new file mode 100644 index 0000000..b470e45 --- /dev/null +++ b/src/components/slides/javascript/08-data-fetching/title.astro @@ -0,0 +1,3 @@ +<section> + <h1>JavaScript: Daten aus dem Backend abfragen</h1> +</section> \ No newline at end of file diff --git a/src/pages/slides/javascript/08-data-fetching.astro b/src/pages/slides/javascript/08-data-fetching.astro new file mode 100644 index 0000000..44cc87c --- /dev/null +++ b/src/pages/slides/javascript/08-data-fetching.astro @@ -0,0 +1,8 @@ +--- +import Reveal from "../../../layouts/Reveal.astro"; +import Slides from "../../../components/slides/javascript/08-data-fetching/index.astro"; +--- + +<Reveal title="JavaScript - Fetch: Daten aus Servern abfragen"> + <Slides /> +</Reveal> \ No newline at end of file