# Fetch API
De Fetch API is een client-side Web API aanwezig in iedere moderne browser (en niet in Node). Het biedt een eenvoudige en flexibele manier om met netwerkverzoeken om te gaan, vooral in combinatie met Promises
en/of async/await
.
# Can I use?
De Fetch API kan je bijna in alle moderne browsers gebruiken, behalve in o.a. Internet Explorer (Afk. IE) en Opera Mini. Als je voor een klant IE moet targetten, dan moet je terugvallen (Eng. fallback) naar de klasse XMLHttpRequest
.

# Syntax
Fetch is een promise-based interface dat ons toelaat om HTTP aanvragen (Eng. requests) te maken via JavaScript code.
# Fetch-functie
De fetch()
-functie is een globale functie aanwezig in moderne webbrowsers. Het wordt gebruikt om netwerkverzoeken te maken en geeft een Promise
terug. Deze Promise
zal je kunnen resolven (met .then()
of async/await
) en geeft vervolgens een Response
van het verzoek terug.
De fetch()
-functie bevat twee argumenten:
- URL: de resource of locatie waarnaar we een aanvraag sturen
- initieel object: waarin we de instellingen van de aanvraag definiëren zoals het soort verzoek.
Het tweede argument is optioneel bij eenvoudige GET
-aanvragen.
Een eenvoudige aanvraag ziet er als volgt uit:
const countriesPromise = fetch("https://restcountries.com/v3.1/all");
console.log(countriesPromise);
setTimeout(() => {
console.log(countriesPromise);
}, 5000);
2
3
4
5
In dit voorbeeld printen we de waarde van countriesPromise
uit. De waarde bevat het object dat de fetch()
-functie teruggeeft. We stellen eveneens een timer in met een delay van 1000
ms, om daarin vervolgens de waarde van de variabele countriesPromise
op te vragen.

De fetch()
geeft direct een Promise
terug met een status pending. Na een delay ontvangen we de status fulfilled. In deze status zit nu een value, namelijk het Response
object die we ontvangen van de resource. De successHandler van het Promise
object wordt vervolgens aangesproken.
Via de then()
functie kunnen we deze successHandler definiëren. Deze handler of callback bevat een argument, namelijk het Response
object.
const countriesPromise = fetch("https://restcountries.com/v3.1/all", {}).then(
(response) => {
console.log(response);
}
);
2
3
4
5
Dat resulteert in de volgende output in de console:

Het Response
object bevat een verzameling van eigenschappen en methoden die we kunnen aanspreken. We kunnen bijvoorbeeld de status opvragen, 200
betekent OK
, 404
betekent NotFound
. Via text()
methode kunnen we de ontvangen data lezen en geeft hierna een Promise
object terug.
const countriesPromise = fetch("https://restcountries.com/v3.1/all").then(
(response) => {
console.log(response.text());
}
);
2
3
4
5
Om effectief de verkregen data te verwerken, moeten we deze Promise
opvangen via een volgende then
functie:
const countriesPromise = fetch("https://restcountries.com/v3.1/all")
.then((response) => {
return response.text();
})
.then((data) => {
console.log(data);
});
2
3
4
5
6
7
Dat resulteert in de volgende output in de console:

Om deze tekst te transformeren naar een object literal pas je de volgende code toe:
const countriesPromise = fetch("https://restcountries.com/v3.1/all")
.then((response) => {
return response.text();
})
.then((textData) => {
const objData = JSON.parse(textData);
console.log(objData);
});
2
3
4
5
6
7
8
Dat resulteert in de volgende output in de console:

Dit kan uiteraard beter geprogrammeerd worden door gebruik te maken van de json()
methode uit het Response
object. Deze methode doet de automatische transformatie van data (tekst of strings) naar een corresponderende object literal, in dit geval een object op basis van een JSON-string:
const countriesPromise = fetch("https://restcountries.com/v3.1/all", {})
.then((response) => {
return response.json();
})
.then((jsonData) => {
console.log(jsonData);
});
2
3
4
5
6
7
Volledig voorbeeld:
const countriesPromise = fetch("https://restcountries.com/v3.1/all", {})
.then((response) => {
if (response.status === 200) {
return response.json();
}
throw Error("Something went wrong!");
})
.then((jsonData) => {
console.log(jsonData);
})
.catch((error) => {
console.log(`Catch: ${error}`);
});
2
3
4
5
6
7
8
9
10
11
12
13
Je kan dit ook omvormen zodat je gebruik kan maken van async
en await
.
const getData = async () => {
try {
const response = await fetch("https://restcountries.com/v3.1/ll");
if (response.status === 200) {
const jsonData = await response.json();
console.log(jsonData);
return;
}
throw Error("Something went wrong!");
} catch (error) {
console.log(`Catch: ${error}`);
}
};
getData();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Fetch settings
De fetch()
-functie ondersteunt verschillende HTTP-methoden (GET, POST, PUT, PATCH, DELETE) en kan worden geconfigureerd met verschillende opties, zoals headers en het lichaam van het verzoek. Dit doen we in het tweede, optionele argument van de functie.
# GET-verzoek - Data ophalen
# Alle resources opvragen
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "GET",
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
Resultaat:

# Eén specifieke resource opvragen
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "GET",
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
Resultaat:

# Resources filteren op basis van query parameters
fetch("https://jsonplaceholder.typicode.com/posts/1?userId=1", {
method: "GET",
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
Resultaat:

# Geneste resources opvragen van een specifieke post via GET request
fetch("https://jsonplaceholder.typicode.com/posts/1/comments", {
method: "GET",
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
Resultaat:

# POST-verzoek - Nieuwe data toevoegen
Een nieuwe resource toevoegen, doen we met een POST-verzoek. We geven de data mee aan de body-key van onze opties en stellen hier optioneel ook headers voor in.
let data = {
title: "Graduaat Programmeren",
body: "Tijdens het Graduaat Programmeren specialiseer je je in JavaScript, HTML, CSS, UI/UX en software engineering. Naast deze technische kant, leer je ook om creatief en commercieel te denken. Als programmeur creëer je namelijk niet alleen aantrekkelijke en functionele websites, maar werk je ook samen met heel wat bedrijven. Na deze opleiding kan je aan de slag als front-end developer, CMS Themer of full-stack JavaScript developer.",
userId: 1,
};
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-type": "application/json; charset=UTF-8" },
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
7
8
9
10
11
12
13
14
# PUT-verzoek - Data vervangen
data = {
id: 1,
title: "Graduaat Programmeren",
body: "Tijdens het Graduaat Programmeren specialiseer je je in JavaScript, HTML, CSS, UI/UX en software engineering. Naast deze technische kant, leer je ook om creatief en commercieel te denken. Als programmeur creëer je namelijk niet alleen aantrekkelijke en functionele websites, maar werk je ook samen met heel wat bedrijven. Na deze opleiding kan je aan de slag als front-end developer, CMS Themer of full-stack JavaScript developer.",
userId: 1,
};
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "PUT",
body: JSON.stringify(data),
headers: { "Content-type": "application/json; charset=UTF-8" },
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# PATCH-verzoek - Data wijzigen
data = {
title: "Graduaat Programmeren: Love Programming Like Graphics",
};
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "PATCH",
body: JSON.stringify(data),
headers: { "Content-type": "application/json; charset=UTF-8" },
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
7
8
9
10
11
12
# DELETE-verzoek - Data verwijderen
fetch("https://jsonplaceholder.typicode.com/posts/1", {
method: "DELETE",
})
.then((response) => response.json())
.then((json) => console.log(json))
.catch((err) => console.log(err));
2
3
4
5
6
# CORS en Same-Origin Policy
De Fetch API volgt de Same-Origin Policy, wat betekent dat het standaard geen verzoeken naar andere domeinen doet. Het is een beveiligingsmechanisme dat in moderne webbrowsers wordt gebruikt om te voorkomen dat webpagina’s middelen (zoals scripts, stijlbladen of afbeeldingen) ophalen van een ander domein dan het domein van de webpagina zelf.
Dit is ontworpen om potentieel schadelijke cross-site-verzoeken te beperken. Cross-Origin Resource Sharing (CORS
) moet worden ingeschakeld op de server om verzoeken naar andere domeinen toe te staan.
// Voorbeeld van een verzoek naar een ander domein (CORS moet zijn ingeschakeld op de server)
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => console.log("Gegevens opgehaald:", data))
.catch((error) => console.error("Fout bij ophalen van gegevens:", error));
2
3
4
5
# CORS, ExpressJS en Live Server
Bij het lokaal ontwikkelen van websites met Live Server en ExpressJS kunnen CORS
-problemen optreden omdat de standaardinstellingen van browsers het uitvoeren van cross-origin verzoeken beperken.
In je ExpressJS-server moet je de juiste CORS-middleware toevoegen om cross-origin verzoeken toe te staan. Dit kan worden gedaan met behulp van de cors-module.
const express = require("express");
const cors = require("cors");
const app = express();
// Gebruik CORS-middleware
app.use(cors());
// Voeg je routes toe...
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server gestart op http://localhost:${PORT}`);
});
2
3
4
5
6
7
8
9
10
11
12
13
De cors()
-middleware zorgt ervoor dat de server de juiste headers retourneert, inclusief Access-Control-Allow-Origin, om cross-origin verzoeken toe te staan.