Using AJAX and JSON in JavaScript
Tags: javascript, webdev, beginners, tutorial
Published: 2020-01-10 03:51:53

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

This is the JSON data that’s parsed by the browser and can be inserted to the DOM of a web page. All AJAX is sending data via HTTP requests and then response will be obtained from the the server, then the data is populated on the page via manipulating the DOM. Most modern browsers work the same way and support AJAX.

Same-Origin Policy
==================

In most cases, requests are made to a server that has a different domain from the originating server. If we do that without setting some options, we will get an error since most browsers by default stop cross-origin requests from being made without setting specific options on the server and the client. The purpose of this is to prevent browsers from downloading code that’s unknown to the browser. This policy applies everywhere, even on our local computer, since it’s can be used to compromise the security of our computers no matter where the data is downloaded from.

To allow requests to request between computers with different domains from a web browser. The server has to enable Cross-Origin Resource Sharing, or CORS for short. This has to be enabled on the server side. If we look at a cross-origin HTTP request, we should see an OPTIONS request before the actual request is made and in we should see the following in the response headers:

```
Access-Control-Allow-Origin: *
```

Alternatively, we can put the client and server-side code in the same domain. This wouldn’t violate the same-origin policy in browsers since the request from the browser is made from the same domain from the server.

Using the XMLHttpRequest Object
===============================

We can use the `XMLHttpRequest` object to make a request to a server and retrieve its response. This can be done with a simple example. In this example, we will load content from a text file and then put the content inside a page. Create a file called `index.html` and add:

```html
<html>  
  <head>  
    <title>XMLHttpRequest</title>  
  </head>  
  <body>  
    <h1>XML HTTP Request</h1>  
    <button id="load">Load Data</button>  
    <div id="content"></div>  
    <script src="script.js"></script>  
  </body>  
</html>
```

The create a file called `script.js` and add:

```javascript
const reqListener = response => {  
  const content = document.getElementById("content");  
  content.innerHTML = response.currentTarget.response;  
};

const loadData = () => {  
  const req = new XMLHttpRequest();  
  req.onload = reqListener;  
  req.open("get", "file.txt", true);  
  req.send();  
};

window.onload = () => {  
  const loadButton = document.getElementById("load");  
  loadButton.onclick = loadData;  
};
```

Then in `file.txt` we put:

```
Hello world.
```

In the above example, we created an instance of the `XMLHttpRequest` object to make a GET request to our server, which is a local web server that servers the `file.txt` file. We call the `open` function to start the request, The first argument is the HTTP request method, which can be `get`, `post`, `put`, `patch` or `delete` . The second argument is the URL or relative path to your server-side resource. The third argument is for setting whether the HTTP request happens asynchronously. Usually, it should be `true` since we do not want to hold up other parts of our JavaScript code from loading. Also, we set the `req.onload` listener function to get the response from the server and then populate the result. In `reqListener` function, we get the `response` from the server when it’s available and then populate the content of the element with ID `content` with it. This happens after we call end `send` function on the `req` object.

Once we have these files we should get ‘Hello world’ when we click ‘Load Data’, we should get ‘Hello world.’ in our page.

This is the simplest case for making HTTP requests and then getting the result with AJAX. If we want to make requests that are more complex, then this is a very cumbersome way to do it. Fortunately, we have the Fetch API. to make a HTTP requests in our client side applications.

Promises
========

In JavaScript, a lot of code are asynchronous since it’s single threaded. To prevent holding up a program by code that finishes running in a indeterminate amount of time, we have to make a lot code asynchronous to prevent holding up the rest of the program from executing.

A promise is an object that represents an asynchronous process that finishes in an indeterminate amount of time. Before it’s executed then its status is pending. It can end in 2 states. If it’s successful, then the promise is resolved. A resolved promised is in the fulfilled state. Otherwise, it ends by by rejecting the promise. A promise is rejected if an error occurred. If an error occurred then the value that’s returned in the promise is ignored. In either case, when the promise finishes executing, a promise is in the settled status. That means settled status includes both fulfilled and error status.

The benefit of using promises for writing asynchronous code is that we can chain multiple promises together as if they are synchronous code. However, promises can only return other promises and they cannot return anything else. They are chained with the `then` function, which takes a callback function which has the resolved value when the promise is fulfilled. When an errors occurred they can be handled with the `catch` function at the end. To execute code no matter what the result of a promise is, we can chain the `finally` function to the end of a promise.

To run an array of promises, we can use the `Promise.all` function, which takes an array of promises.

An example of a promise would be something like:

```javascript
const getTextPromise = new Promise((resolve, reject) => {  
  const xhr = new XMLHttpRequest();  
  xhr.open('GET', 'file.txt', true);  
  xhr.onload = (response) => resolve(response.currentTarget.responseText);  
  xhr.onerror = () => reject(xhr.statusText);  
  xhr.send();  
});
```

We wrapped the example we have above inside a promise and we resolve the response text instead of populating it in the DOM directly. To populate it in the DOM, we do:

```javascript
getTextPromise  
.then(responseText =>{  
  const content = document.getElementById("content");  
  content.innerHTML = responseText;  
})  
.catch(error =>{  
  alert(error.toString());  
})
```

Make HTTP Requests with the Fetch API
=====================================

The Fetch API makes use of promises to make asynchronous HTTP requests from the browser to a server. It provides us with an easy to use API for making requests. It lets us create HTTP requests with a `Request` object, then when the server makes a response, then we get a `Response` object. We make a request with the `fetch` method. The `fetch` method takes one mandatory, which includes all the data for making requests. Once the `Response` object is returned then we can massage it to get it to the form we want and then populate it in our web pages.

Also, it’s aware of concepts like CORS, so we can make cross-origin requests if the server allows by setting some options within the argument of the `fetch` method. To use the `fetch` method for making HTTP request, we can do it with an example. If we want to make a form for letting users subscribe to your email list, we can write the following code. Create a file called`index.html` and add:

```html
<html>  
  <head>  
    <title>Email List Subscribe Form</title>  
  </head>  
  <body>  
    <h1>Email List Subscribe Form</h1>  
    <form action="" name="nameForm" id="nameForm" method="post">  
      <label for="firstName">First Name: </label>  
      <input type="text" name="firstName" id="firstName" /><br />  
      <label for="lastName">Last Name: </label>  
      <input type="text" name="lastName" id="lastName" /><br />  
      <label for="email">Email: </label>  
      <input type="text" name="email" id="email" /><br />  
      <input type="submit" value="Subscribe" />  
    </form>  
    <script src="script.js"></script>  
  </body>  
</html>
```

to add the form. Then create a `script.js` file in the same folder and add:

```javascript
const APIURL = "http://localhost:3000";
const subscribe = data => {  
  return fetch(`${APIURL}/subscribers`, {  
    method: "POST",  
    mode: "cors",  
    cache: "no-cache",  
    headers: {  
      "Content-Type": "application/json"  
    },  
    body: JSON.stringify(data)  
  })
  .then(response => response.json());  
};

window.onload = () => {  
  const nameForm = document.forms.nameForm;  
  nameForm.method = "post";  
  nameForm.target = "_blank";  
  nameForm.action = "";  
  nameForm.addEventListener("submit", e => {  
    e.preventDefault();  
    const firstName = document.getElementById("firstName").value;  
    const lastName = document.getElementById("lastName").value;  
    const email = document.getElementById("email").value;  
    let errors = [];  
    if (!firstName) {  
      errors.push("First name is required.");  
    } 

    if (!lastName) {  
      errors.push("Last name is required.");  
    } 

    if (!email) {  
      errors.push("Email is required.");  
    } 

    if (!/\[^@\]+@\[^\.\]+\..+/.test(email)) {  
      errors.push("Email is invalid.");  
    } 

    if (errors.length > 0) {  
      alert(errors.join(" "));  
      return;  
    }  
    subscribe({  
      firstName,  
      lastName,  
      email  
    })
    .then(response => {  
      alert(`${response.firstName} ${response.lastName} has subscribed`);  
    });  
  });  
};
```

The `subscribe` function is where we used the `fetch` method. In there we pass in the URL of the server we are making the request to as the first argument. In the second argument, we set the method, which the HTTP request method for the request we want to make, which is POST. `mode` should be CORS since we’re making a cross domain request. We don’t want any request caching so we set `cache` to `no-cache` . In `headers` , we set `Content-Type` to `application/json` to make the requests data type send JSON. The `body` is the request body of the request, which we create a JSON object since we are sending JSON to the server. Finally, we return `response.json()` , which is a promise with the response if the request is successful sent back from the server and converted to JSON format.

To send something to the URL we point to we have to set up a web server. We first install the `json-server` package by running `npm i json-server`. Then, go to our project folder and run:

```bash
json-server --watch db.json
```

In `db.json`, change the text to:

```json
{  
  "subscribers": []  
}
```

So we have the `subscribers` endpoints defined in the `requests.js` available.

Shorten Promise Code with Async and Await
=========================================

The code above makes use of several promises. We have one for making the request, and then another one for converting it to JSON. Then finally, we make the `alert` at the end. With the `then` function, we make to put callback functions as an argument of all of our `then` functions. This makes the code long is we have lots of promises. Instead, we can use the `async` and `await` syntax to replace the `then` and its associated callbacks as follows. In `script.js`, we put:

```javascript
const APIURL = "http://localhost:3000";
const subscribe = async data => {  
  const response = await fetch(`${APIURL}/subscribers`, {  
    method: "POST",  
    mode: "cors",  
    cache: "no-cache",  
    headers: {  
      "Content-Type": "application/json"  
    },  
    body: JSON.stringify(data)  
  });  
  return response.json();  
};

window.onload = () => {  
  nameForm.method = "post";  
  nameForm.target = "_blank";  
  nameForm.action = "";  
  nameForm.addEventListener("submit", async e => {  
    e.preventDefault();  
    const firstName = document.getElementById("firstName").value;  
    const lastName = document.getElementById("lastName").value;  
    const email = document.getElementById("email").value;  
    let errors = [];  
    if (!firstName) {  
      errors.push("First name is required.");  
    } 

    if (!lastName) {  
      errors.push("Last name is required.");  
    } 

    if (!email) {  
      errors.push("Email is required.");  
    } 

    if (!/\[^@\]+@\[^\.\]+\..+/.test(email)) {  
      errors.push("Email is invalid.");  
    } if (errors.length > 0) {  
      alert(errors.join(" "));  
      return;  
    }  
    try {  
      const response = await subscribe({  
        firstName,  
        lastName,  
        email  
      });  
      alert(`${response.firstName} ${response.lastName} has subscribed`);  
    } catch (error) {  
      alert(error.toString());  
    }  
  });  
};
```

We replaced the `then` and callbacks with `await` . Then we can assign the resolved values of each promise as variables. Note that if we use `await` for our promise code then we have to put `async` in the function signature like we did in the above example. To catch errors, instead of chaining the `catch` function at the end, we use the `catch` clause to do it instead. Also, instead of chaining the `finally` function at the bottom to run code when a promise ends, we use the `finally` clause after the `catch` clause to do that instead.

`async` functions always return promises, and cannot return anything else like any other function that uses promises.

With the Fetch API and `async` and `await` syntax, we can make HTTP requests to servers much more easily than using the old `XMLHttpRequest` object. This is why now more and more web applications are using AJAX instead of refreshing the whole page on server side to get data.