What is Ajax β Asynchronous Web Communication
After completing this topic
You will understand the principle of Ajax, which allows you to exchange data with the server without refreshing the page, and you will be able to send GET/POST requests using the fetch API.
The Problem with Refreshing
In traditional web development, when you request something from the server, the entire page is reloaded. When you type a search query and press Enter, the screen flashes white and the entire results page is reloaded.
Google Search is different. When you type a search query, suggested search terms appear below. The page does not refresh. This is Ajax β it retrieves data from the server without reloading the page, only fetching the necessary data.
Ajax stands for Asynchronous JavaScript and XML, but these days it uses JSON instead of XML. It's a case of the name remaining while the technology evolves.
The Old Way β XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data);
}
};
xhr.send();As you can see, it's cumbersome. You have to check the readyState value, check the status code, and parse the response yourself. If this code is nested in callbacks, it becomes what is known as "callback hell."
The Current Standard β fetch API
const response = await fetch('/api/users');
const data = await response.json();
console.log(data);Three lines. Since fetch returns a Promise, it combines naturally with async/await.
GET β Retrieving Data
async function getUsers() {
const res = await fetch('/api/users');
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const users = await res.json();
return users;
}Note that fetch does not reject on 404 or 500. It only rejects on network errors (server connection failure). Therefore, you must check res.ok (whether it's 200ο½299) yourself.
POST β Sending Data
async function createUser(name, email) {
const res = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email }),
});
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return await res.json();
}Convert the data to be placed in the body to a string using JSON.stringify, and set the Content-Type to application/json. If this header is missing, the server will not parse the body as JSON.
Real-World Pattern β Loading/Error/Success
const resultDiv = document.getElementById('result');
async function loadUsers() {
resultDiv.textContent = 'Loading...';
try {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`Server error: ${res.status}`);
const users = await res.json();
resultDiv.textContent = users
.map(u => `${u.name} (${u.email})`)
.join('\n');
} catch (err) {
resultDiv.textContent = `Error: ${err.message}`;
}
}Managing these three states (loading/success/error) is a recurring pattern in front-end development. In React, you would use useState to create the same structure, and in Vue, you would use ref.
fetch vs XMLHttpRequest Comparison
| XMLHttpRequest | fetch | |
|---|---|---|
| Syntax | Callback-based, verbose | Promise-based, concise |
| JSON Parsing | Manual: JSON.parse(xhr.responseText) | Provides .json() method |
| Error Handling | Check readyState + status manually | res.ok + try/catch |
| Streaming | Not possible | Supports ReadableStream |
| Abort | xhr.abort() | AbortController |
| Cookie Transmission | Included by default | Requires explicitly specifying credentials: 'include' |
Common Mistakes
- Missing
Content-Typeβ If you don't include theheadersin a POST request, the server cannot parsereq.body. - Calling
.json()Twice βres.json()can only be called once. The body stream is exhausted after it is read once. - CORS Error β When you fetch from a different domain, the browser will block the request. You must set the
Access-Control-Allow-Originheader on the server.
Key Takeaway
Ajax is a technology that allows you to exchange data with the server without refreshing the page. In modern web development, the
fetchAPI +async/awaitis the standard. Sincefetchonly rejects on network errors, be sure to always checkres.ok.