Maart 2020, de verjaardag van Ajax ... Soort van. De eerste implementatie van XMLHttpRequest, ook wel bekend als XHR is in leven gekomen in 1999, als een IE 5.0 ActiveX component ( geen vragen a.u.b. ).
Voor die tijd, zijn er manieren geweest om gegevens van een server te halen zonder dat er een pagina volledig te herladen, maar vaak vertrouwden deze op onhandige manieren zoals <Script> injectie of third-party plug-ins.
Microsoft heeft XHR primair ontwikkeld als browser-based alternatief voor hun outlook e-mail cliënt.
XHR was geen standaard van het web tot in 2006, maar het was al geïmplementeerd in de meeste browsers. Hierna heeft ook gmail en google maps dit geïntegreerd, waarnaar een artikel verscheen "Ajax : A new approach to web applications" wat met open armen werd ontvangen door een hoop ontwikkelaars.
Ajax naar Ajax
Ajax oftewel "Asynchronous Javascript en XML". "Ascynchronis", zeker ... Maar :
- Javascript was waarschijnlijk, desondanks dat VBScript en flash opties waren die gebruikt konden worden.
- De payload geen XML nodig had, toch was dit erg populair. Alle data formats konden gebruikt worden, en vandaag de dag is dat JSON ( aangezien elke taal JSON kan verwerken, en onderling met elkaar kan delen ).
We gebruiken nu Ajax als algemene term ( verbeter me als ik fout zit )? Voor elke cliënt-side proces dat gegevens ophaalt van een server en de DOM dynamisch bijwerkt zonder een pagina volledig te herladen.
Ajax is een core techniek voor de meeste web applicaties en "Single page applicaties" (SPA's)
Extreme XHR
De volgende code is een simpel voorbeeld van hoe een XHR HTTP request eruit ziet :
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/page');
xhr.onreadystatechange = function() {
//Is de request klaar?
if(xhr.readyState !== 4) return;
if(xhr.status === 200) {
//Request is binnen, toon de response
console.log(xhr.responseText);
} else {
console.log('Er is een error!',xhr.status, xhr.statusText)
}
}
//Start de request
xhr.send();
De XHR Object heeft vele opties, events en response properties, zoals xhr.timeout
en xhr.upload.onprogress
,
De opties kunnen verbijsterend zijn en vroege implementatie van XHR hadden een aantal cross-browser inconsistenties waardoor niet alles lekker verliep in verschillende browsers. Hiervoor is de reden, dat de meeste libraries en frameworks gebruik gingen maken van Ajax wrapper functies om de complexiteit tegen te gaan, zoals in dit voorbeeld de jQuery.ajax()
method :
$.ajax('http://example.com/page')
.done(data => console.log(data))
.fail((xhr, status) => console.log('Er is een error!', status));
Fetch
De 'Fetch API' is een modern alternatief voor XHR. De generieke Headers, Request en Response interfaces zorgen hierbij voor consistentie terwijl 'Promises' eenvoudiger chaining en 'async/await' toelaat ZONDER callbacks!!.
De XHR hierboven kan makkelijk geconverteerd worden naar een simpelere Fetch-based code die zelfs parsed JSON terugstuurt :
fetch('http://example.com/page', {
method: 'GET'
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Er is een error!', error));
Fetch is elegant, clean en veel makkelijker te begrijpen. Het is veel voorkomend in PWA service workers ( en uiteraard voor web API's ). Desondanks is web ontwikkeling nooit zo eenduidig. Fetch is 'nog' geen volledige vervanging van Ajax technieken, maar hier word wel hard aan gewerkt.
Browser support
De fetch API is vrijwel in elke browser bruikbaar, maar het zal niet werken in alle versies van IE of oudere releases van Chrome, Firefox en Safari ouder dan 2017. Controleer dit dus altijd voordat je hier in duikt terwijl je een groot project gaat starten of al doet voor een klant dit scheelt je een hoop uurtjes extra werk.
Errors worden niet afgekeurd
Verassend genoeg, een HTTP error zoals een 404 of 500 word niet afgekeurd door de Fetch Promise; de .catch()
zal dus niet behandeld worden. In plaats word de response.ok
status op false gezet. Afkeuring ( Reject ) gebeurt alleen wanneer een request niet compleet is, zoals een netwerk storing etc. waardoor het wat lastiger kan zijn om een duidelijke error vermelding te krijgen.
Timeouts worden niet ondersteund
De meeste die wel eens met een API gewerkt hebben, weten wel dat alles soms wat te vlot gaat en er een timeout gemaakt moet worden om data door te drukken. De Fetch API heeft helaas geen ingebouwde functionaliteiten hiervoor, maar is het wel mogelijk om gewoon de timeout in een specifieke Promise te wrappen :
function fetchTimeout(url, init, timeout = 1000) {
return new Promise((resolve, reject) => {
fetch(url, init)
.then(resolve)
.catch(reject);
setTimeout(reject, timeout);
});
}
XHR vs Fetch?
De keuze is aan jou! Tenzij je een IE applicatie hebt waarbij klanten een progress bar willen hebben.
Voor makkelijkere calls, XHR is lower-level, gecompliceerder en je zal vaak tegenkomen dat je wrapper functies nodig hebt. Helaas ... Is dit bij Fetch hetzelfde wanneer je overweegt om aan de gang te gaan met timeouts, call aborts en error trapping.
Fetch is de toekomst. Maar, de API is relatief nieuw, en support nog niet alle XHR functies, en sommige opties zijn omslachtig. Gebruik het met wijsheid voor de aankomende jaren!