Skip to content
On this page

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 /api an eine separate Serverinstanz weiterzuleiten.
  • nginx oder apache als 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.

Dogs

HTTP Api für "dogs"

Unter der URL https://dog.ceo/api/breeds/image/random erhalten Sie mit einem GET Request eine JSON Antwort.

  1. Führen Sie den GET Request mit dem Webbrowser aus. (Was ist die einfachste Methode hierzu?)
  2. Verwenden Sie auf dem Gastsystem curl um den API Request auszuführen.
  3. Installieren Sie die VS Code Extension Thunder Client und 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.

HTML und CSS

  • Erstellen Sie wie in den vorherigen Versuchen eine HTML Seite mit jeweils einem JS main.js und style.css.
  • Designen Sie style.css so, dass Sie ein statisches Bild mit der URL https://images.dog.ceo/breeds/kelpie/n02105412_4038.jpg anzeigen und das Layout wie im Beispiel auf dem Bildschirm zentrieren. Die Dimensionen des Bildes sind für Breite und Höhe jeweils 200px.
  • Achten Sie darauf, dass der html resp. body Tag by default nicht 100% 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();
  1. Erstellen Sie ein onload Callback und führen Sie einen Request via fetch aus.
  2. Das onload Callback soll dabei async sein, da wir die fetch API mit await aufrufen werden.
  3. Führen Sie den fetch aus um das Resultat vom Server zu erhalten.
  4. Schauen Sie sich das JSON Resultat an. Wie erhalten Sie den Link für das img Element?
  5. Mit document.querySelector() können Sie eine Referenz auf das img Element erhalten.
  6. Im DOM können Sie mit .setAttribute() ein Attribut eines Elements setzen (welches Attribut müssen Sie bei <img> setzen um die Bildresource anzuzeigen?).
  7. Erstellen Sie nun eine Funktion updateImage(), welche den fetch ausführt und das Bild aktualisiert.
  8. In onload registrieren Sie nun einen onlclick Listener auf dem img Element, welcher die updateImage() Methode aufruft.