Web APIsMedium

How does AJAX work?

01

The Short Answer

AJAX (Asynchronous JavaScript and XML) is a technique for making HTTP requests from the browser without reloading the page. It lets you fetch data from a server, send form submissions, and update parts of the page dynamically — all in the background while the user continues interacting with the page. Despite the name, modern AJAX almost always uses JSON instead of XML. The technique was revolutionary because before AJAX, every server interaction required a full page reload.

02

Before AJAX — Full Page Reloads

Before AJAX, web applications worked in a request-response cycle where every user action that needed server data caused a full page reload. Click a link? New page. Submit a form? Page reloads. Check for new messages? Refresh the page. This made web apps feel slow and clunky compared to desktop applications. AJAX changed this by allowing the browser to communicate with the server in the background.

  • User performs an action (clicks button, submits form, scrolls)
  • JavaScript creates an HTTP request in the background
  • Request is sent to the server asynchronously (page stays interactive)
  • Server processes the request and sends back data (JSON, HTML, XML)
  • JavaScript receives the response and updates only the relevant part of the page
  • No page reload — seamless user experience
03

AJAX with XMLHttpRequest (Original)

The original AJAX implementation used XMLHttpRequest (XHR). You create a request object, configure it with the HTTP method and URL, set up a callback for when the response arrives, and send it. The readyState property tracks the request lifecycle (0 = unsent, 4 = done), and you check the status for HTTP response codes. This is verbose but shows exactly what AJAX does under the hood.

ajax-xhr.jsjavascript
// Classic AJAX with XMLHttpRequest
function loadUserData(userId) {
  const xhr = new XMLHttpRequest();

  // Configure: method, URL, async (true)
  xhr.open('GET', `/api/users/${userId}`, true);

  // Set up response handler
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) { // Request complete
      if (xhr.status === 200) {
        const user = JSON.parse(xhr.responseText);
        document.getElementById('username').textContent = user.name;
        document.getElementById('email').textContent = user.email;
      } else {
        console.error('Request failed:', xhr.status);
      }
    }
  };

  // Send the request
  xhr.send();
}

// AJAX POST — sending data to the server
function submitComment(postId, comment) {
  const xhr = new XMLHttpRequest();
  xhr.open('POST', `/api/posts/${postId}/comments`, true);
  xhr.setRequestHeader('Content-Type', 'application/json');

  xhr.onload = function() {
    if (xhr.status === 201) {
      const newComment = JSON.parse(xhr.responseText);
      appendCommentToDOM(newComment); // Update UI without reload
    }
  };

  xhr.send(JSON.stringify({ text: comment }));
}

The pattern is always the same: create request → configure → set callback → send. The callback fires when the response arrives, and you update the DOM with the new data. The page never reloads — only the relevant section changes.

04

Modern AJAX with Fetch

Today, the Fetch API is the standard way to make AJAX requests. It uses Promises instead of callbacks, works with async/await, and has a cleaner API. The concept is identical — asynchronous HTTP requests without page reloads — but the developer experience is dramatically better. Most modern applications use Fetch directly or through libraries like Axios.

ajax-fetch.jsjavascript
// Modern AJAX with Fetch + async/await
async function loadUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const user = await response.json();

    // Update only the relevant part of the page
    document.getElementById('username').textContent = user.name;
    document.getElementById('email').textContent = user.email;
  } catch (error) {
    document.getElementById('error').textContent = 'Failed to load user';
  }
}

// AJAX POST with Fetch
async function submitComment(postId, comment) {
  const response = await fetch(`/api/posts/${postId}/comments`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text: comment }),
  });

  if (response.ok) {
    const newComment = await response.json();
    appendCommentToDOM(newComment);
  }
}

// Real-world example: search-as-you-type
const searchInput = document.getElementById('search');
let debounceTimer;

searchInput.addEventListener('input', (event) => {
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(async () => {
    const query = event.target.value;
    if (query.length < 2) return;

    const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
    const results = await response.json();
    renderSearchResults(results); // Update dropdown without page reload
  }, 300);
});

The search-as-you-type example shows AJAX at its best — the user types, requests fire in the background, and results appear instantly without any page navigation. This pattern powers autocomplete, live search, infinite scroll, and real-time updates across the web.

05

Common AJAX Patterns

  • Lazy loading:
    • Load content only when needed (scroll, tab click, expand)
    • Reduces initial page weight and speeds up first paint
  • Polling:
    • Repeatedly fetch data at intervals (setInterval + fetch)
    • Simple but inefficient — replaced by WebSockets for real-time
  • Infinite scroll:
    • Detect scroll position → fetch next page of results
    • Append new items to the list without navigation
  • Form submission:
    • Submit via AJAX → show success/error inline
    • No page reload, better UX, can show validation errors instantly
  • Optimistic updates:
    • Update UI immediately, send request in background
    • Revert if request fails — feels instant to the user
06

AJAX vs Modern Alternatives

TechnologyDirectionUse case
AJAX (Fetch/XHR)Client → Server (request/response)Standard data fetching, form submissions, CRUD operations
WebSocketsBidirectional (persistent connection)Real-time chat, live updates, multiplayer games
Server-Sent EventsServer → Client (one-way stream)Live feeds, notifications, stock tickers
GraphQLClient → Server (flexible queries)Complex data requirements, avoiding over/under-fetching
React Server ComponentsServer → Client (streaming HTML)Next.js — server renders components, streams to client
07

Why Interviewers Ask This

AJAX is foundational web knowledge. Interviewers ask this to verify you understand how client-server communication works in the browser, know the difference between synchronous page loads and asynchronous requests, can explain the evolution from XHR to Fetch to modern data-fetching libraries, understand common patterns (polling, optimistic updates, debounced search), and know when AJAX is appropriate versus WebSockets or SSE. It's also a gateway to discussing error handling, loading states, and race conditions in async code.

Quick Revision Cheat Sheet

What AJAX does: Makes HTTP requests in the background — updates page without reload

Original tool: XMLHttpRequest (XHR) — event-based, verbose, still used for upload progress

Modern tool: Fetch API — Promise-based, clean, works with async/await

Key benefit: Partial page updates — only change what's needed, no full reload

Common patterns: Search-as-you-type, infinite scroll, form submission, lazy loading

Not AJAX: WebSockets (persistent bidirectional), SSE (server push) — different protocols