fetch: Daten aus dem Web
Dauer: ca. 45 Minuten
- JavaScript im Browser hat eine
fetch
-Funktion für Web-Daten node-fetch
stellt diese in NodeJS bereit (ab NodeJS 18 nativ!)fetch
ist asynchron und liefert Promisesasync/await
vereinfacht den Umgang mit Promises
Ziel: Daten von Webservice-APIs einbinden
Am Beispiel des Wetterdienstes Open-Meteo wollen wir die aktuelle Temperatur für Berlin abfragen.
Die kostenlose und frei zugängliche API (application programming interface) von Open-Meteo kann dazu mit folgender URL (Web-Link) angefragt werden:
https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true
Die Koordinaten für Berlin (Breitengrad 52.51, Längengrad 13.41) werden als Parameter in der URL übermittelt, sodass der Server die gewünschte Anfrage ausführen und das Ergebnis als JSON-Daten liefern kann.
Im Browser steht JavaScript eine Funktion
fetch
zur Verfügung, mit der Daten aus dem Web
via URL z.B. als JSON angefordert werden können.
⟶ URL im Browser laden und fetch
mit
open-meteo.com in der Browser-Konsole vorführen.
node-fetch
Ab Version 18 ist fetch
in NodeJS enthalten (vorerst als experimentelles Feature).
In NodeJS bzw. replit.com kann die Funktionalität
von fetch
durch die Installation der Bibliothek
node-fetch
dem Projekt hinzugefügt werden.
Danach kann fetch
wie folgt zur Verwendung im Code
importiert werden:
import fetch from 'node-fetch';
fetch
verwenden
Nun kann fetch
in replit.com bzw. NodeJS
wie im Browser verwendet werden.
Da ein Netzwerkzugriff mit fetch
unter
Umständen etwas länger dauern kann (z.B.
bei langsamer Internetverbindung), läuft
fetch
asynchron bzw. „im Hintergrund“ ab.
Das Ergebnis von fetch
ist daher ein
Promise-Objekt, das mit Callback-Funktionen
asynchron verarbeitet werden muss.
Promises
stellen ein etwas schwer zugängliches Thema in
JavaScript dar. Für die Verwendung von fetch
besprechen wir hier nur das Nötigste.
Die Verwendung von fetch
und Promises läuft
folgendermaßen ab:
fetch
mit URL aufrufen, dies liefert ein Promise-Objekt- das Promise-Objekt enthält eine
response
, die mit der Methodejson()
die JSON-Daten liefert response
im Promise-Objekt kann mitthen
ausgelesen werden — hierbei wird ein Callback inthen
benötigtthen
liefert wieder ein Promise-Objekt, das das JavaScript-Objekt basierend auf den JSON-Daten enthält- dieses kann wiederum mit
then
und Callback-Funktion verarbeitet werden
Der Code in der Funktion
getBerlinWeatherPromiseSteps()
zeigt,
wie dies umgesetzt wird:
import fetch from 'node-fetch';
function getBerlinWeatherPromiseSteps() {
const url =
`https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true`;
// 1. Schritt: fetch ausführen
// --> Das Ergebnis ist ein Promise-Objekt
const fetchPromise = fetch(url);
// 2. Schritt: aus dem fetchPromise die
// JSON-Daten durch response.json() mit Callback in then() auslesen
// --> then liefert wieder ein Promise-Objekt
const dataPromise =
fetchPromise.then(response => response.json());
// 3. Schritt: aus dem dataPromise die relevanten Daten mit then() ausgeben
dataPromise.then(data => console.log(data.current_weather.temperature));
}
Da die einzelnen Aufrufe von then
wiederum
Promises liefern, können diese direkt
miteinander kombiniert werden (dies wird
„chaining“ genannt):
function getBerlinWeatherPromiseChained() {
const url =
`https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true`;
fetch(url)
.then(response => response.json())
.then(data => console.log(data.current_weather.temperature));
}
Somit ist die Verwendung von fetch
bereits
einigermaßen kompakt und übersichtlich
möglich.
Promises mit then
kann schnell zu
unübersichtlichem Code führen. Alternativ kann
async/await
zum Einsatz kommen.
async/await
für Promises
Mit async/await
wird die Verarbeitung von
Promises leichter nachvollziehbarer.
Der Code der obigen Funktionen kann ebenso
mit async/await
ausgedrückt werden.
Dazu ist eine Funktion mit dem Schlüsselwort
async
vor function
zu deklarieren:
// Die Funktion ist nun asynchron!
async function getBerlinWeatherAwait() {
const url =
`https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true`;
const response = await fetch(url);
const data = await response.json();
console.log(data.current_weather.temperature);
return data.current_weather.temperature;
}
await
löst einen Promise auf und liefert
das Ergebnis zurück. Gleichzeitig „wartet“
(await) der Code auf die Verarbeitung, sodass
der Code einem „normalem“ synchronen Ablauf
syntaktisch ähnelt.
⟶ await
ist nur dann in einer Funktion erlaubt,
wenn diese mit async
deklariert wurde!
Der Rückgabewert einer async
-Funktion ist
wiederum ein Promise, der automatisch von
JavaScript erzeugt wird. Um den „eigentlichen“
Rückgabewert im Promise einer async
-Funktion
zu verwenden, muss dieser mit await
in einer
weiteren async
-Funktion angefragt werden:
async function berlinTemperature() {
const temp = await getBerlinWeatherAwait();
console.log("Temperatur in Berlin: " + temp);
}
berlinTemperature();
Beim Zugriff auf APIs bzw. Webservices mit fetch
können
verschiedene Fehlersituationen eintreten:
- keine Internetverbindung,
- Server ist nicht erreichbar,
- Antwort des Servers passt nicht zum erwarteten Ergebnis,
- u.a.
Daher sollte ein Webzugriff mit fetch
z.B. mit
try…catch
-Blöcken umgeben werden, um
Fehlersituationen im Code zu behandeln.
Dieser Artikel beschreibt ausführlich, was bei der Verwendung von fetch
zu beachten ist, und zeigt praktische Code-Beispiele:
www.builder.io/blog/safe-data-fetching