There aren’t many websites and web applications these days that don’t utilize XHRs. In fact, if you want to build an application or website that pulls in data from an API, chances are, you’re going to have to send XHRs to GET the data.
What is an XHR? XHR stands for XMLHttpRequest; It’s a browser-based javascript object used for requesting and transmitting data from and to a web service (API.) What sets it apart from using a standard HTTP request is that it is asynchronous and will not force a page reload.
What this allows us to do is change elements on a web page without the browser reloading/refreshing. This is very useful for bringing the “Desktop App”-like experience to the web. *Cough* Single Page Apps
Making use of XHRs
When it comes to using XHRs , there are many roads you can take. Let’s talk about a few of the more widely used implements. Here, have some Chuck Norris jokes too.
XMLHttpRequest
This is the oldest implementation of XHR out of all the methods I’ll discuss in this post. It’s native to the browser and has the highest compatibility out of all the other methods.
In exchange for the compatibility it’s also one of the more painful ones to read as you’ve got to remember the readystate states. I suppose one way around this is to use an enum to map the states to something more semantic. Still, it’s a bit bulky and it doesn’t support the use of service workers.
//Utilizing XHRs //Initializing the XHR javascript object const XHR = new XMLHttpRequest(); //There are 5 states an XHR object can be in /* 0 - Unsent : open() hasn't been called yet 1 - Opened: open() has been called 2 - Headers Received: send() has been called and headers and status can be veiewed 3 - Downloading: responseText holds partial data 4 - Done: operation is complete */ //The lowercase actually matters here on this function XHR.onreadystatechange = () => { /* //This uncommented line below effectively states that if the XHR request is done and the response was OK (status 200) then send a toast/alert with the chuck norris joke from the chuck norris jokes API. The responseText property holds the response from the XHR request in stringified form. The function JSON.parse() parses the stringified JSON and turns it into a javascript object We then send an alert with the data stored inside of object's value.joke property */ (XHR.readyState == 4 && XHR.status == 200) ? alert(JSON.parse(XHR.responseText).value.joke) : null; } //These two lines "open" the XHR object and configures it to send to the designated endpoint (second parameter) and then calls the send() method to actually send the XHR off XHR.open("GET", "https://api.icndb.com/jokes/random"); XHR.send(); //Try running this in Chrome Developer Console --> Press F12 go to console, copy and paste this code //This will only work in a Browser that implements alert
Fetch
This is the more modern implementation of XMLHttpRequest. Fetch is also native to the browser; this means that you do not have to import anything with respects to the front end when developing for web browsers.
The readability of Fetch is heaps and bounds above its predecessor. And, with a slew of other benefits (such as the ability to use service workers) this is the one I prefer to use.
As Fetch is younger, the compatibility is just a tiny bit less robust. IE isn’t supported at all, for example–and that can be a deal breaker for many. To get around this you can always use a polyfill.
//Utilizing the Fetch API to send XHRs //Because fetch is native to the browser you can just call it //The default behavior for Fetch is to GET fetch("https://api.icndb.com/jokes/random") .then(res => res.ok? res.json() //Because Fetch does not throw an error on status messages we do our own manual check here .then(parsedData => alert(parsedData.value.joke)) //parse the data and output the joke via alert : alert(<code>Something was wrong with the request: ${res.status}:${res.statusText} </code>) //Send an alert/toast describing what the response status was ) .catch((err) => alert(err)) //Fetch will throw an error with errors other than HTTP status errors (like if you don't have a network connection)
Axios
Axios is a third party library that is made specifically for web requests. Because it is a third party library, you must import/include it before using it unlike the previous two.
In general the Axios syntax is a lot easier on the eyes. This is true especially when you start to tack on request options.
One of the benefits of using Axios is that you don’t have to parse responses coming in, it’s just automatically ready to be used as a Javascript object.
Another major advantage of Axios is that the .catch() block will actually catch HTTP status 400 errors unlike Fetch where you have to implement your own HTTP status 400 error catching.
//Utilizing Axios to send XHRs //axios is not native to the browser environment so you would have to include it via html script tag axios.get("https://api.icndb.com/jokes/random") .then(res => alert(res.data.value.joke)) //send alert with the joke .catch(err => alert(<code>There was a problem with the request! ${err.response.status}: ${err.message}</code>)) //response status 400s are actually caught in the catch block of Axios. Neat!
Decisions…decisions..
All in all, each implementation of XHR has its benefits and its drawbacks. Similar to how a pen is just a tool to a writer, it is up to the developer to analyze and assess which method would be the ideal choice for a project.
Do you want your code to be as legible as it can be? Maybe Axios is your cup of tea.
Want to strike a balance between how clean your code base is, while limiting the usage of third party libraries? Fetch, boy!
Looking to break free from the chains that bind? Raw, primeval, untamed and unchained: these are the adjectives that describe the person who wishes to use the default XHR API. Perhaps your target platform is Internet Explorer 8. Then, naked XHRs will set you free my guy/gal. (We don’t judge around here.)
The power is in your hands. Choose wisely, or not. *shrugs*