Code Tutorials

Tutorial: in JavaScript (ES6) mit einer API kommunizieren

Daten von einer API (Application Programming Interface/Programmierschnittstelle) abzurufen und zu verarbeiten ist eine häufige Aufgabe, mit der man sich als Programmierer befassen muss. In vielen Frameworks gibt es dafür alle möglichen Hilfsmittel, es geht aber auch problemlos mit „Vanilla“ JavaScript, insbesondere dank ES6, also der neusten Version von JavaScript.

Bei der Recherche zu dem Thema bin ich über einen tollen Blogpost gestolpert, der die Thematik mithilfe der Ghibli-API erklärte. Ich wusste bis dato nicht von der Existenz einer Ghibli-API und war demzufolge sofort begeistert. Die Studio Ghibli API kann hier gefunden und kostenlos verwendet werden. Sie liefert unter anderem alle Filme des Anime-Studios, aber auch alle vorkommenden Personen, Orte oder fremde Spezies aus den Filmen.

Hinweis: Andere offene APIs zum Ausprobieren sind zum Beispiel die Star Wars API oder die Pokémon API, die beide recht ähnlich funktionieren.

Ziel dieses Tutorials

Wir werden eine Webseite erstellen, die sämtliche Filme des Studio Ghibli chronologisch anzeigt und verschiedene Zusatzinfos zu den jeweiligen Filmen zeigt. Die Seite wird simpel mit HTML und CSS Grid aufgebaut, die API-Anbindung findet über JavaScript (ES6) statt.

Hier seht ihr das Ergebnis, wie die Seite am Ende aussehen soll (oder direkt auf Github):

Ghibli API CS Grid

Erste Schritte

Zuerst sollte man sich mit einer API vertraut machen, bevor man sie benutzt. Viele APIs sind leider nur unzureichend dokumentiert, was es gerade Anfängern nicht leicht macht. Außerdem gibt es zu viele Möglichkeiten (und unterschiedliche Programmiersprachen), mit einer API zu kommunizieren, als dass eine Dokumentation sie alle abdecken könnte. Wir schauen uns dennoch die Webseite der Studio Ghibli API an, auf der ein paar Beispielabfragen gezeigt werden.

Da die API ohne spezielle Authentifizierung funktioniert, kann man auch jeden Aufruf (API Call) direkt über den Browser betrachten. Gibt man beispielsweise „https://ghibliapi.herokuapp.com/films“ in seine Adresszeile ein, bekommt man direkt im Browser die Antwort angezeigt, nämlich eine Auflistung sämtlicher Filme im JSON-Format. Schön und gut, aber wie rufen wir diese Daten mit JavaScript ab, verarbeiten sie und stellen sie auf unserer Webseite dar?

Zuerst brauchen wir eine Seite. Dazu erstellen wir uns im Editor unserer Wahl eine index.html, für die schönere Darstellung kommt noch eine style.css dazu und für den Code eine main.js, alle auf derselben Ebene. Normalerweise ist das nicht die feine Art, aber in diesem einfachen Beispiel soll uns das mal egal sein. Die Inhalte der index.html und style.css interessieren uns in diesem Tutorial nicht, deshalb kannst du die einfach hier herunterladen/kopieren (style.css + index.html). Die main.js werden wir nun Schritt für Schritt füllen.

Verbindung zur API herstellen

Wir benutzen die neue fetch-API, um mit der Ghibli-API zu kommunizieren und speichern das Ergebnis in der Konstante „request“:

const request = fetch('https://ghibliapi.herokuapp.com/films');

In „request“ ist jetzt das Gleiche gespeichert, was wir auch gesehen haben, als wir die URL im Browser aufgerufen haben. Im nächsten Schritt müssen wir diese Daten weiter verarbeiten.

request.then(data => data.json())

Hier passieren direkt mehrere (neue) Dinge. Einmal benutzen wir das „Promise-Objekt“, das für API-Anfragen perfekt ist. Promises können drei Status haben, pending, fulfilled und rejected. Ein Promise ist erst im Zustand pending und kann in den Zustand fulfilled oder rejected wechseln, in diesen Zuständen können mit .then oder .catch Handler aneinandergereiht und aufgerufen werden. Das kann dann so aussehen:

request 
   .then() //tu dies
   .then() // dann das
   .catch() //mach das hier, wenn es einen Fehler gab

Das andere, was vielleicht ungewohnt aussieht, ist die Fat-Arrow-Schreibweise und die kompakte Schreibweise einer Funktion in einer Zeile ohne geschweifte Klammern. Auch dazu gäbe es viel mehr zu sagen, wichtig ist für das Verständnis aber hier nur, dass

data => data.json()

das gleiche ist als würden wir

function(data) { 
   return data.json()
}

schreiben. Hier nochmal der gesamte Code bisher, inklusive einem console.log, mit dem wir überprüfen, ob auch alles klappt.


const request = fetch('https://ghibliapi.herokuapp.com/films');
request
  .then(data => data.json())
  .then(data => {
    console.log(data);
  })
  .catch((err) => {
    console.error(err);
  });

Funktion überprüfen: wenn du die index.html nun im Browser öffnest, siehst du erstmal nichts. Über „Element untersuchen“ (Google Chrome) kannst du die „Console“ einsehen, dort sollte nun die Antwort der API-Anfrage zu sehen sein. (console.log(data) schreibt die Variable data in die Browser-Konsole)

Mit einem Klick auf den Pfeil am Anfang kannst du dir die Antwort im Detail anschauen, bzw. die einzelnen Objekte untersuchen.

Wir sehen nun die einzelnen Bezeichnungen im Film-Objekt: description, director, title… diese können wir direkt ansprechen. Über eine forEach-Schleife lassen wir uns sämtliche Titel ausgeben (die vorherige console.log-Zeile kann weg):

data.forEach(movie => {
  console.log(`${movie.title} (${movie.release_date})`);
});

Hier haben wir direkt ein paar Kleinigkeiten, die neu in ES6 sind. Einmal die forEach-Schleife, die du vielleicht aus anderen Programmiersprachen kennst. Diese for-Schleife führt eine Funktion pro Array-Element aus. Früher hätte man das mit einer for-Schleife in etwa so gelöst:

for(i = 0; i < Array.length; i++) {
//Code
}

Mit der forEach-Schleife geht das eleganter und einfacher.
Das zweite sind die sogenannten Template Literals, die man mit den `Backticks` einfügt. Damit lassen sich viel leichter Variablen und Strings kombinieren. Da das hier kein ausführliches ES6-Tutorial werden soll, nur ganz kurz und ohne viel Erklärung. Mit Backticks/Template Literals wird aus

console.log(movie.title + '(' + movie.release_date + ')');

ganz einfach das

console.log(`${movie.title} (${movie.release_date})`);

Umfasst man Strings mit ` ` können Variablen (und mehr) ganz leicht mit ${var} eingefügt werden.

Darstellung

Eigentlich haben wir jetzt schon alles, was wir haben wollten. Mit movie.title, movie.description, movie.release_date usw. können wir uns alle Daten aller Filme anzeigen lassen. Die Ghibli API kann noch viel mehr und wir könnten viel komplexere Anfragen stellen, wie zum Beispiel „nenne mir die Namen sämtlicher Katzen aus allen Ghibli Filmen“ oder „zeige mir den Film, bei dem Joe Hisaishi nicht die Musik gemacht hat“, aber das vielleicht ein anderes Mal.

Allerdings wollen wir die Daten ja noch in unsere index.html bekommen und nicht nur in der Browser-Konsole betrachten.

In JavaScript lassen sich leicht HTML-Elemente erstellen und mit Inhalt befüllen, auch ohne jQuery.

const title = document.createElement('h2');
title.textContent = `${movie.title} (${movie.release_date})`;

Diese zwei Zeilen erzeugen ein h2-Element, speichern es als Konstante mit Namen title und fügen dann mit textContent den gewünschten Inhalt – in dem Fall den Titel und das Datum eines Films – zwischen die h2-Tags. Das wiederholen wir für die Elemente „Regisseur“ (Director) und die Beschreibung (Description):

const title = document.createElement('h2');
title.textContent = `${movie.title} (${movie.release_date})`;

const director = document.createElement('p');
director.textContent = `Directed by: ${movie.director}`;

const desc = document.createElement('p');
desc.textContent = `${movie.description}...`;

Jetzt müssen wir die Elemente noch in unsere kleine HTML-Seite bekommen. Diese besteht ja eigentlich nur aus einem DIV mit der ID „app“. Dieses DIV sprechen wir in unserem JavaScript an und fügen ihm die Elemente hinzu. Ganz oben in unserer main.js deklarieren wir dazu ein paar Variablen.

const app = document.getElementById('app');
const movies = document.createElement('div');
movies.setAttribute('class', 'movies');
app.appendChild(movies);

Wir haben eine Konstante „app“ in der wir das DIV mit der ID „app“ abspeichern. Dann kreieren wir ein neues DIV (document.createElement(‚div‘)) und speichern es unter dem Namen „movies“ (in das DIV kommen alle unsere Filme), in der Zeile darunter geben wir dem gerade erzeugten DIV noch die entsprechende Klasse „movies“.
app.appendChild(movies) fügt das movies-DIV dem app-DIV hinzu. Die erzeugte HTML-Datei sähe nun so aus:

Ein leeres movies-DIV

In der forEach-Schleife (jeder Durchlauf steht für einen Film) erzeugen wir auf die gleiche Art ein DIV pro Film und geben dem DIV die Klasse „moviedetail“:

const moviedetail = document.createElement('div');
moviedetail.setAttribute('class', 'moviedetail');

Ganz unten in der forEach fügen wir jedes movieDetail-DIV dem movies-DIV hinzu und geben dem DIV die vorher definierten Elemente title, director und desc.

movies.appendChild(moviedetail);
moviedetail.appendChild(title);
moviedetail.appendChild(director);
moviedetail.appendChild(desc);

Hier nochmal die gesamte main.js im Überblick:

const request = fetch('https://ghibliapi.herokuapp.com/films');

const app = document.getElementById('app');
const movies = document.createElement('div');
movies.setAttribute('class', 'movies');
app.appendChild(movies);

request
  .then(data => data.json())
  .then((data) => {
    // console.log(data);
    data.forEach((movie) => {
      const moviedetail = document.createElement('div');
      moviedetail.setAttribute('class', 'moviedetail');

      const title = document.createElement('h2');
      title.textContent = `${movie.title} (${movie.release_date})`;

      const director = document.createElement('p');
      director.textContent = `Directed by: ${movie.director}`;

      const desc = document.createElement('p');
      desc.textContent = `${movie.description}...`;

      movies.appendChild(moviedetail);
      moviedetail.appendChild(title);
      moviedetail.appendChild(director);
      moviedetail.appendChild(desc);
    });
  })
  .catch((err) => {
    console.error(err);
  });

Das war es auch schon. Wir sehen jetzt alle Ghibli-Filme mit Erscheinungsjahr, Regisseur und Kurzbeschreibung, wenn wir die index.html im Browser aufrufen.

Wer mag, tobt sich ein wenig im CSS aus, fügt mehr Infos wie den Rotten-Tomatoes-Score dazu oder versucht sich daran, eine Abfrage nach den Orten, Personen oder Lebewesen zu integrieren. (Mit https://ghibliapi.herokuapp.com/people bekommt man beispielsweise alle Personen, das müsste man dann allerdings noch mit der ID des jeweiligen Films kombinieren, um auf alle Personen, die in einem Film mitspielen, zu kommen.)

Das fertige Ergebnis seht ihr auf Github.

Kommentar verfassen