JSON with AJAX and XMLHttpRequest
What is AJAX?
AJAX stands for Asynchronous JavaScript and XML. Despite the name including "XML," AJAX is most commonly used with JSON today. AJAX is a technique that allows a web page to load or send data in the background without refreshing the entire page.
Before AJAX, every time new data was needed, the whole page had to reload. AJAX changed this — now only the data is fetched, and the page updates only the part that changed. This creates a much smoother user experience, like how Gmail loads new emails or how a search box shows suggestions while typing.
The original built-in method for making AJAX requests is XMLHttpRequest (often shortened to XHR). While the modern Fetch API is now preferred, understanding XHR is important because it is still widely used in older codebases and projects.
How XMLHttpRequest Works — Step by Step
- Create a new
XMLHttpRequestobject - Define what happens when the response arrives (the callback)
- Open a connection — specify the HTTP method (GET or POST) and the URL
- Send the request
- Receive the response and parse the JSON
Basic GET Request — Fetching JSON Data
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data.name);
console.log(data.email);
}
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/users/1", true);
xhr.send();Let's understand what each part does:
new XMLHttpRequest()— creates the request objectonreadystatechange— a function that runs every time the request state changesreadyState === 4— means the request is completestatus === 200— means the server responded with successxhr.responseText— the raw JSON string returned by the serverJSON.parse()— converts the string into a usable JavaScript object
Understanding readyState Values
| Value | State Name | Meaning |
|---|---|---|
| 0 | UNSENT | Request has not been opened yet |
| 1 | OPENED | The open() method has been called |
| 2 | HEADERS_RECEIVED | Request has been sent; headers received |
| 3 | LOADING | Response body is being received |
| 4 | DONE | Request is complete — response is ready |
Using the onload Event (Cleaner Approach)
Instead of checking readyState, the onload event fires only when the request is fully complete — making the code simpler:
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status === 200) {
const user = JSON.parse(xhr.responseText);
console.log("Name: " + user.name);
console.log("City: " + user.address.city);
} else {
console.log("Request failed. Status: " + xhr.status);
}
};
xhr.onerror = function() {
console.log("Network error occurred.");
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/users/2", true);
xhr.send();Fetching a List (Array) of JSON Records
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status === 200) {
const posts = JSON.parse(xhr.responseText);
console.log("Total posts: " + posts.length);
posts.slice(0, 3).forEach(function(post) {
console.log(post.title);
});
}
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts", true);
xhr.send();Displaying XHR Response in HTML
<div id="result"></div>
<script>
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status === 200) {
const user = JSON.parse(xhr.responseText);
const container = document.getElementById("result");
container.innerHTML =
"<h3>" + user.name + "</h3>" +
"<p>Email: " + user.email + "</p>" +
"<p>Phone: " + user.phone + "</p>";
}
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/users/4", true);
xhr.send();
</script>POST Request — Sending JSON Data to a Server
To send JSON data (like form submissions) to a server using XHR:
const xhr = new XMLHttpRequest();
const payload = {
title: "Study Plan",
body: "Complete all JSON topics this week.",
userId: 7
};
xhr.onload = function() {
if (xhr.status === 201) {
const response = JSON.parse(xhr.responseText);
console.log("Created post with ID: " + response.id);
}
};
xhr.open("POST", "https://jsonplaceholder.typicode.com/posts", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(payload));Key steps for a POST request:
- Use
xhr.open("POST", url, true) - Set the
Content-Typeheader toapplication/json - Convert the object to a string using
JSON.stringify()before sending - A status of
201means the resource was successfully created
XHR vs Fetch API — Quick Comparison
| Feature | XMLHttpRequest (XHR) | Fetch API |
|---|---|---|
| Introduced | Early 2000s (legacy) | 2015 (modern) |
| Code Style | Callback-based (nested) | Promise-based (chainable) |
| Readability | More verbose | Cleaner and simpler |
| async/await Support | Not directly | Yes, natively |
| Browser Support | All browsers including older IE | All modern browsers |
| When to Use | Legacy code, older projects | New projects (preferred) |
Key Points to Remember
- AJAX allows data to be loaded in the background without refreshing the page
XMLHttpRequestis the original AJAX tool — still found in legacy codebases- Always check
readyState === 4andstatus === 200before reading the response xhr.responseTextreturns the raw JSON string — always parse it withJSON.parse()- For POST requests, set the
Content-Typeheader and stringify the data before sending - For new projects, the
Fetch APIis the modern and recommended alternative
Summary
XMLHttpRequest was the original way to make background HTTP requests in JavaScript and is still encountered frequently in existing web applications. Understanding XHR alongside the Fetch API gives a complete picture of how web pages communicate with servers using JSON. The core workflow remains the same in both approaches — send a request, receive a JSON string response, parse it, and use the data.
