Appearance
Async HTTP mit JS
Folgende Ziele werden in diesem Versuch angestrebt
- HTML Webseite erstellen
- Seite mit CSS und Flexbox stylen
- Mit JavaScript asynchrone Requests an Web API ausführen
- HTTP Response parsen
- DOM der Webseite änderen um den Inhalt der Server Response zu visualisieren.
In diesem Versuch arbeiten wir vollständig Clientseitg (wir verwenden eine öffentliche API eines HTTP Servers, welche wir selber implementieren).
Moderne Webapplikationen arbeiten mit APIs, welche Nutzdaten (häufig in JSON) zur Verfügung stellen. Dabei wird die API kein CSS oder HTML liefern, dieses wird separat gehostet. In diesen Versuch erstellen wir wieder eine statische HTML und CSS Seite im Filesystem des Gastsystems (die Webseite wird also nicht einmal über einen lokalen HTTP Server geliefert).
Trennung von Client und Server
Der Webbrowser konsumiert HTML, CSS und JS. Hinzu kommen oft Bilder, Videos und andere Medien. Das Hosting von solchen statischen Files (das HTML, JS und CSS bleibt meistens immer gleich) ist nicht rechenintensiv, verbraucht aber trotzdem RAM und Netzwerkkapazität vom Server.
Aus diesem Grund wird in skalierbaren Webapplikationen meistens ein dedizierter HTTP "Fileserver" verwendet, der diese statischen Inhalte vom Filesystem liest und für den Client bereitstellt.
Dienste wie AWS S3 und Shared Webhosting sind auf diese operationen spezialisiert und sind im Vergleich zu einem dedizierten Serverdienst wie flask, expressjs oder django kostengünstig zu erhalten.
Aus diesem Grund wird die API meistens getrennt implementiert. Folgende Ansätze werden oft praktiziert:
- Separate Subdomain (und IP) für API
- Loadbalancer der Cloud Infrastruktur
- um z.B. Requests nach
/apian eine separate Serverinstanz weiterzuleiten.
- um z.B. Requests nach
nginxoderapacheals Loadbalancer auf dem eigenen Server mit reverse proxy.
Web Applikation Dogs
In dieser Applikation wird eine öffentlich zugängliche API verwendet, bei welcher man einen JSON als Response erhält und deren Inhalt einen Link zu einem zufälligen Bild mit einem Hund beinhaltet.
Der Link wird ausgelesen und als http resource für ein Bild verwendet.
Click man auf das Bild, dann wird ein neuer Request ausgelöst und das nächste Bild gelanden.

HTTP Api für "dogs"
Unter der URL https://dog.ceo/api/breeds/image/random erhalten Sie mit einem GET Request eine JSON Antwort.
- Führen Sie den GET Request mit dem Webbrowser aus. (Was ist die einfachste Methode hierzu?)
- Verwenden Sie auf dem Gastsystem
curlum den API Request auszuführen. - Installieren Sie die VS Code Extension
Thunder Clientund führen Sie den Request auch hier aus.
Aufgabe
Was erhalten Sie für eine Antwort? Wie kommen Sie an die Image Resource?
Wenn Sie den Request mit Thunder Client ausführen sehen Sie eine Reihe Headers in der Response. Für was steht dabei access-control-allow-origin?
Recherchieren Sie hierzu folgenden Blogeintrag https://www.freecodecamp.org/news/access-control-allow-origin-header-explained/.
Webseite Implementieren
Toolset
Folgen Sie im Vorfeld folgenden Beiträgen, die für den Versuch wichtig sind.
- IMG Element mit Link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#image_link
- Object Fit Property für images: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
- Wenn Sie das Beispiel anschauen, welche
object-fitProperty ist die passende, die wir verwenden wollen? - Fetch API mit HTTP Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
HTML und CSS
- Erstellen Sie wie in den vorherigen Versuchen eine HTML Seite mit jeweils einem JS
main.jsundstyle.css. - Designen Sie
style.cssso, dass Sie ein statisches Bild mit der URLhttps://images.dog.ceo/breeds/kelpie/n02105412_4038.jpganzeigen und das Layout wie im Beispiel auf dem Bildschirm zentrieren. Die Dimensionen des Bildes sind für Breite und Höhe jeweils200px. - Achten Sie darauf, dass der
htmlresp.bodyTag by default nicht100%der Höhe des Bildschirms umfassen.
JS window.onload
Die HTTP API, die wir verwenden werden ist folgende: https://dog.ceo/api/breeds/image/random. Wir führen dabei einen GET Request aus. Keine weiteren Parameter sind notwendig (weder Headers noch Request Parms als URL encodierung).
Promises, async und await
Funktionen können Promise objekte zurückgeben. Ein Promise liefert hier nicht sofort das Resultat, sondern braucht im Hintergrund etwas Zeit, bis das Resultat zur Verfügung steht. Die fetch API liefert hier ein Promise zurück.
js
const result = fetch("https://dog.ceo/api/breeds/image/random");
// was ist im Resultat drin?
console.log('result', result);
// callback registrieren, wenn result returned
result.then((httpRes) => {
// resultat des Requests ist hier als param erhältlich.
console.log('res', httpRes);
// JSON muss geparsed werden, hierzu gibt es auch wieder ein Promise
const jsonPromise = httpRes.json();
jsonPromise.then((json) => {
// endlich haben wir das resultat!!
console.log('json result', json);
});
});
Das Beispiel zeigt, dass wir bereits relativ nahe an der sogennanten "Callback Hell" sind, da wir gezwungen sind funktionen ineinander zu verschachteln.
Das async und await Feature schafft hierbei Abhilfe. Wollen wir auf ein Resultat mit await warten, müssen wir uns in einem async Context befinden. Das ist relativ einfach machbar, in dem dass wir eine Funktion mit dem async Keyword deklarieren. Wir dürfen nicht vergessen, diese später aufzurufen. Natürlich könnten wir auch einfach unsere window.onload Methode async deklarieren, dann wäre ein manueller Aufruf nicht notwendig.
Folgender Code führt zum gleichen Resultat wie oben.
js
const start = async () => {
const res = await fetch('https://dog.ceo/api/breeds/image/random');
const json = await res.json();
console.log('json', json);
}
start();
- Erstellen Sie ein
onloadCallback und führen Sie einen Request viafetchaus. - Das
onloadCallback soll dabeiasyncsein, da wir diefetchAPI mitawaitaufrufen werden. - Führen Sie den
fetchaus um das Resultat vom Server zu erhalten. - Schauen Sie sich das JSON Resultat an. Wie erhalten Sie den Link für das
imgElement? - Mit
document.querySelector()können Sie eine Referenz auf das img Element erhalten. - Im DOM können Sie mit
.setAttribute()ein Attribut eines Elements setzen (welches Attribut müssen Sie bei<img>setzen um die Bildresource anzuzeigen?). - Erstellen Sie nun eine Funktion
updateImage(), welche denfetchausführt und das Bild aktualisiert. - In
onloadregistrieren Sie nun einenonlclickListener auf demimgElement, welcher dieupdateImage()Methode aufruft.