AJAX Demystified - What Is AJAX?
Tags: designpattern, javascript
Published: 2021-12-29 21:16:08

---
title: AJAX Demystified - What Is AJAX?
published: true
date: 2021-12-29 12:03:40 UTC
tags: DesignPattern,JavaScript
series: Design Patterns, JavaScript
canonical_url: https://www.underthehoodlearning.com/ajax-demystified-what-is-ajax
cover_image: https://res-3.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/AJAX.png
---

In [Part 1](https://dev.to/thanhtr99270163/ajax-demystified-why-do-we-need-ajax-388d) of this series, we laid the foundation for learning AJAX by digging deep into the history of web development at the time when AJAX was created. In this next part of the series, we will learn what **AJAX** really is.

## What is AJAX?

We learned from the previous blog post that AJAX was created to solve the problem with the "annoying" delay in the responsiveness of a sovereign web application. An AJAX application, therefore, eliminates the _start-stop-start-stop_ nature of interaction on the Web by implementing a collection of four technologies that complement one another: **CSS,  DOM, JavaScript,** and **XMLHttpRequest**.

- **JavaScript (JS):** JavaScript is the glue that holds everything together in an AJAX application. JS is used to _define user workflow and business logic of the app, manipulates and refreshes the UI via the DOM to continually redraw and reorganize the data presented to the users based on user's interactions via mouse and keyboard event handling._
- **CSS:** In an AJAX application, the styling of a UI may be modified interactively through CSS.
- **DOM:** The **DOM** presents the structure of web pages as a set of programmable objects that can be manipulated with JS. Scripting the DOM allows an AJAX application to modify the UI on the fly, effectively redrawing parts of the page.
- **XMLHttpRequest:** The XMLHttpRequest object allows data retrieval from the webserver asynchronously. The data format is typically **XML** , but it works well with any text-based data. Nowadays,  the most common data format used for this is **JSON.**

It's worth mentioning that three of the four technologies listed above ( **CSS, DOM, JS** ) have been collectively referred to as **Dynamic HTML (DHTML).**  DHTML offered the ability to create interactive UI for web pages. However, it never overcame the issue of the full-page refresh since without communicating with the server, there was only so much it could do. AJAX makes considerable use of DHTML, but with the ability to make asynchronous requests to the server, AJAX has a lot more to offer.

## XMLHttpRequest

**XMLHttpRequest** is a **native API** in JS that encapsulates the logic of sending HTTP requests without having to refresh a loaded web page - _ **AJAX request.** _ Even though developers rarely use XMLHttpRequest directly now, it's still the building block that works underneath many popular HTTP request modules such as [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) and [Axios](https://github.com/axios/axios).

The complete lifecycle of loading a document using XMLHttpRequest is as follows: _instantiate the XMLHttpRequest object, tell it to load a document, and then monitor that load process asynchronously using callback handlers.  _

Now that you understand the high-level concept of AJAX, let's jump into some codes.👩‍💻 Let's try to implement AJAX using Vanilla JS. Why would we want to do that if there are several frameworks out there that have out-of-the-box AJAX technology? It's because we want to learn _"under the hood"_, remember?😉

## AJAX using Vanilla JS

We will be implementing AJAX using Vanilla JS to build a simple web application as shown below. When the **Retrieve** button is clicked, a "Hello World!" message returned by the backend server via an AJAX call is displayed right below the button without a page refresh. Try it for yourself!👇

<iframe width="1000" height="500" src="https://codesandbox.io/embed/ajax-vanilla-js-b0snd?file=/src/index.js" style="width:1000px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>

A simple AJAX implementation takes four steps:

- Create an instance of the `XMLHttpRequest` (aka `XHR`) object
- Use the `open()` method of the `XHR` to specify what kind of data you want
- Create a function to process the response
- Use the XHR's `send()` method to send the request

Now, let's look at some code. For this simple demo, we have a simple backend web server written in **Node.js** to process AJAX requests. For the UI on the frontend, we have a simple HTML and a script for the **Retrieve** button's event handling.

### Node.js Backend Web Server

The code for our **Node.js** web server is defined in the `index.js` file located in the root directory.

<!--kg-card-begin: markdown-->
```
var http = require("http");
var fs = require("fs");

function render(path, contentType, fn) {
  fs.readFile(__dirname + "/" + path, "utf-8", function (err, str) {
    fn(err, str, contentType);
  });
}

//create a server object:
http
  .createServer(function (req, res) {
    var httpHandler = function (err, str, contentType) {
      if (err) {
        console.log(err);
        res.writeHead(500, { "Content-Type": "text/plain" });
        res.end("An error has occured: " + err.message);
      } else {
        res.writeHead(200, { "Content-Type": contentType });
        res.end(str);
      }
    };
    if (req.url.indexOf("/scripts/") >= 0) {
      console.log("Serving ajax.js");
      render(req.url.slice(1), "application/javascript", httpHandler);
    } else if (
      req.headers["x-requested-with"] === "XMLHttpRequest" &&
      req.headers["x-vanillaajaxwithoutjquery-version"] === "1.0"
    ) {
      console.log("Processing AJAX request");
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ message: "Hello World!" }));
    } else {
      console.log("Serving index.html");
      render("views/index.html", "text/html", httpHandler);
    }
  })
  .listen(8080); //the server object listens on port 8080

```
<!--kg-card-end: markdown-->

Here, we're using the [`http` module](https://nodejs.org/api/http.html) to create an **HTTP server.** For those of you that are not familiar with **Node.js,** here is a brief explanation of the code.

The server is listening on Port `8080`. The callback function we pass to the `createServer()` method is executed for each request that comes in. Whenever a new request is received, the `request` event is called, providing two objects: a **request** (an `http.IncomingMessage` object) and a **response** (an `http.ServerResponse` object). The `request` provides the request details through which we can access the request `headers` and request `data`. The `response` is used to populate the data returning to the client.

<!--kg-card-begin: markdown-->
```
var http = require("http");

//create a server object:
http
  .createServer(function (req, res) {
    // callback to handle request is define here
  })
  .listen(8080); //the server object listens on port 8080

```
<!--kg-card-end: markdown-->

Let's look at the callback function used to handle requests.

<!--kg-card-begin: markdown-->
```
if (req.url.indexOf("/scripts/") >= 0) {
  render(req.url.slice(1), "application/javascript", httpHandler);
} else if (
  req.headers["x-requested-with"] === "XMLHttpRequest" &&
  req.headers["x-vanillaajaxwithoutjquery-version"] === "1.0"
) {
  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify({ message: "Hello World!" }));
} else {
  render("views/index.html", "text/html", httpHandler);
}

```
<!--kg-card-end: markdown-->

This block of code checks the request URL to determine how the app should respond.

- If the request came from the `scripts` directory, then the appropriate file is served with the `application/javascript` content type. 
- Any request with `x-request-with` headers set to `XMLHttpRequest` indicates an **AJAX** request. In this case, we simply return a "Hello World!" text message.
- If it's neither of the two cases above, then the `index.html` file is served.

We haven't discussed the `render()` and `httpHandler()` functions yet, so let's do that now.  The `render()` function asynchronously reads the contents of the requested file. It accepts the `httpHandler()` callback function, which is used to check for errors and write the content of the file to the response with the appropriate HTTP status code if everything looks good.

<!--kg-card-begin: markdown-->
```
function render(path, contentType, fn) {
  fs.readFile(__dirname + "/" + path, "utf-8", function (err, str) {
    fn(err, str, contentType);
  });
}

```
<!--kg-card-end: markdown--><!--kg-card-begin: markdown-->
```
var httpHandler = function (err, str, contentType) {
  if (err) {
    console.log(err);
    res.writeHead(500, { "Content-Type": "text/plain" });
    res.end("An error has occured: " + err.message);
  } else {
    res.writeHead(200, { "Content-Type": contentType });
    res.end(str);
  }
};

```
<!--kg-card-end: markdown-->
## Frontend UI Code

Now, let's look at our frontend code, which contains the `/views/index.html` file and the `/scripts/ajax.js` script used for the button event handling. The `index.html` is straightforward. It references the `ajax.js` script which is called when the user clicks the **Retrieve** button.

<!--kg-card-begin: markdown-->
```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Vanilla Ajax without jQuery</title>
  </head>
  <body>
    <h1>Vanilla Ajax without jQuery</h1>
    <button id="retrieve" data-url="/">Retrieve</button>
    <p id="results"></p>
    <script src="/scripts/ajax.js" async></script>
  </body>
</html>

```
<!--kg-card-end: markdown-->

The `ajax.js` script is where most of the AJAX magic happens.

<!--kg-card-begin: markdown-->
```
(function () {
  var retrieve = document.getElementById("retrieve"),
    results = document.getElementById("results"),
    toReadyStateDescription = function (state) {
      switch (state) {
        case 0:
          return "UNSENT";
        case 1:
          return "OPENED";
        case 2:
          return "HEADERS_RECEIVED";
        case 3:
          return "LOADING";
        case 4:
          return "DONE";
        default:
          return "";
      }
    };
  retrieve.addEventListener("click", function (e) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      console.log(
        "Inside the onreadystatechange event with readyState: " +
          toReadyStateDescription(xhr.readyState)
      );
      if (xhr.readyState === 4 && xhr.status === 200) {
        if (xhr.responseType === "json") {
          results.innerHTML = xhr.response.message;
        } else {
          results.innerHTML = JSON.parse(xhr.responseText).message;
        }
      }
    };
    xhr.open("GET", e.target.dataset.url, true);
    xhr.responseType = "json";
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("x-vanillaAjaxWithoutjQuery-version", "1.0");
    xhr.send();
  });
})();

```
<!--kg-card-end: markdown-->

We followed the five steps to implement AJAX described in the previous sections:

<!--kg-card-begin: markdown-->
1. Create an `xhr` instance of the `XMLHttpRequest` object using the XMLHttpRequest() constructor.

2. Use the `open()` method of the `XMLHttpRequest` object to specify the kind of data being requested. It takes three arguments:

3. Create a callback function to process the response. `XHR` has two properties used to indicate a response from the server:

4. Finally, all we're left to do is send the request. But before we do that, we need to make sure we set the _ **request headers** _ accordingly to indicate that our request is indeed an AJAX request.

<!--kg-card-end: markdown-->
## Tie it all together

Let's tit it all together - _frontend and backend._ When we start the server by running `npm run start`, the server returns the rendered `index.html` page to the browser. Since the `index.html` file references the `ajax.js` script, the browser issues another request to the server to get this file. Finally, when the user clicks the **Retrieve** button, the server returns the "Hello World!" message. This workflow can be observed via the server's terminal logger as shown below.

<!--kg-card-begin: markdown-->
```
Serving index.html
Serving ajax.js
Processing AJAX request

```
<!--kg-card-end: markdown-->
## AJAX Implementations

Below are some examples of AJAX implementations for your references:

- **Auto-suggestion:** Almost all search engines nowadays have this feature implemented. However, it's not limited to just search engines. In fact, it can be used in any text box in web forms.
- **Infinite scrolling:** Infinite scrolling is also implemented using AJAX. As the user scrolls downwards, more contents are fetched from the server and displayed on the page.
- **Self-Updating Stock Ticker:** Most trading sites have the stock tickers updated with the latest rates on the market automatically without reloading the entire page.
- **Form Validation:** For example, when a user enters an email address to sign up for an account, the user's input is sent to the database to check if it's an existing account. Depending on the server's response, the user is either allowed to proceed to the next step or an error is displayed on the screen. This whole process can be done asynchronously without reloading the whole page.