Tutorials
05 Jun 2020

Learn AJAX: Part 2

By Benji

The universally supported base API for AJAX is called XMLHttpRequest(). We often shorten that to XHR. It is so very much harder for AJAX newcomers to grasp, mostly because the many parts of the HTTP request get separated out into separate pieces of the XHR. If you mess up any of those parts, you won’t have your data. People want their data. People should read this blog.

This is Part 2 of a tutorial on the basics of AJAX, for beginners. You might want to start at Part 1 if you haven’t already.

Disclaimer! This article is for beginners, but it does assume a basic knowledge of HTTP’s structure. If you know the meaning of GET and POST, read on! Otherwise, I highly recommend going straight to the Wikipedia source and boning up.

While I do expect you to know what HTTP requests are, I’m not expecting you to be familiar with our forefathers and their seminal work on making HTTP requests by hand with web servers. You are not (yet) that server gal 🧛‍♀️. You are not (yet) Richmond.

An Ill Wind is Blowing

cURL is Really Capitalized Like That

In the beginning, there was a thing called cURL. It underpins a lot of HTTP requests from languages like PHP. It still exists, and it’s used in many places. Part of it is worth explaining here, but the rest can always be found here.

cURL is cool because it’s a playground for talking to the internet without a GUI. It can be used as a command line tool, and it lets you build custom HTTP requests from your terminal! cURL is a good place to learn about HTTP, which you already know, right? I hope so.

For each section of an HTTP request, cURL has an option. There are naturally many options. They are grouped by type, like headers, cookies, urls, post-types, and ports. There are many defaults, but it’s common to need to set more than one of these before executing the actual request. It’s similar in XHR.

But First, You Must Instantiate!

In my opinion, XHR is the closest thing that old-timey JavaScript can have to a class. It has a lot of sensitive settings, and there can be more than one at a time, so the first thing you’ll do is use the XMLHttpRequest() cookie cutter and stamp out a new Object.

let xhr = new XMLHttpRequest();                   // assign this to a variable to instantiate it
xhr.open(POST, yoururl.com/something.json, true); // request-type, url, async (true/false)

Tell It What You Want

The next part of a POST request will often require specific headers. It’s possible and common to use these headers to set encoded OAuth keys and values into the request to open up gateways with APIs. It’s also common to use headers to define your data. You know, normal HTTP header things go here. Naturally, this must always be done after you .open() your request and before you .send() it.

xhr.setRequestHeader("Content-Type", "application/json");

// What was that .... you wanted more than one header field? Easy, do it as many times as you need:
xhr.setRequestHeader("Cookie", 'siteName=Monjibram');
xhr.setRequestHeader("Referer", 'https://www.monjibram.com');

Make It An Event

Your response is now today years old! But what happens when it grows up, travels the world, and returns home? You can set your event handler next, with any callbacks you need.

xhr.onreadystatechange = function() {
    // in plain English: if the request is finished and it received a 200 status
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
        // Request finished. Process asynchronously from here with a callback.
        console.log(this.response);
    } else {
        // There could be a multitude of reasons that something failed. Error log here.
        console.log(this);
    }
}

Wrap Things Up

All that to send some formData. If you recall from Part 1, we were attempting to AJAX this wee little form:

Of course you’re welcome to send any sort of data string you please via HTTP. With the URLSearchParams() API you can even transform JSON and JS Objects into useful parameters.

Whatever happens, you’re now ready to send that little form’s contents out into the big, big world. Give it the boot with .send(). If this were a GET request, .send() would accept the parameters on the url you’re looking to pull from. It can also accept null.

const params = new URLSearchParams({
  email: document.getElementById('email').value,
  foo: "Benji", // and more
  bar: "<3",    // and more
  baz: "AJAX",  // and more!
});

xhr.send(params);

Examples of XHR with GET and POST

POST

let xhr = new XMLHttpRequest();
xhr.open(POST, yoururl.com/something.json, true);
xhr.setRequestHeader("Content-Type", "application/json");

xhr.onreadystatechange = function() {
    // in plain English: if the request is finished and it received a 200 status
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
        // Request finished. Process asynchronously from here with a callback.
        console.log(this.response);
    } else {
        // There could be a multitude of reasons that something failed. Error log here.
        console.log(this);
    }
}

const params = new URLSearchParams({
  email: document.getElementById('email').value,
  foo: "Benji", // and more
  bar: "<3",    // and more
  baz: "AJAX",  // and more!
});

xhr.send(params);

GET

var url = "https://feed.podbean.com/covertocredits/feed.xml";
var xhr = new XMLHttpRequest();

xhr.open("GET", url, true);

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
        if (xhr.status == 200) {
            if (xhr.responseText != null) {
                podcastAttributes = xhr.responseXML.getElementsByTagName('item');
                console.log(podcastAttributes[0]);
            } else {
                alert("Failed to receive RSS file from the server - file not found.");
                return false;
            }
        } else {
            alert("Error code " + xhr.status + " received: " + xhr.statusText);
        }
    }
};

xhr.send(null);

A Short Rant

This was the way I think you should learn about XHR. After jQuery, and before Fetch and Axios.

On the other hand, this is how Mozilla thinks you should learn XHR. There are no base examples, only a long list of properties and methods. Navigating to Using XHR is a real doozy. It contains no single example of a POST request, but instead jumps off on a multi-section tangent about recreating native form submissions. I usually highly recommend the Moz Docs, but in this case you should approach with caution.

Next Time…

We’ve completed the average jQuery AJAX request, and followed through the base XHR request, but two modern AJAX-friendly APIs have been integrated in modern front-end frameworks. The basics of Axios and Fetch will round out our triad of beginner tutorials on asynchronous JavaScript calls.


About the Author:

Benji is a professional web dude. He works at Top Hat making cool web things for money (and sometimes beer).

Disclaimer! Photos on this blog are sometimes taken by me, but sometimes free for use with attribution from Unsplash.com.