AlgoDaily

AJAX and Fetch API

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

From DOM To Data

From page interaction to live data

In DOM Manipulation, you wired user actions to page changes. That gives you a local, interactive UI.

Now we add the next layer: data that lives somewhere else.

AJAX lets a page talk to a server in the background, so the user does not have to reload the whole page. The modern browser tool for this is the Fetch API.

Think of it like upgrading a puzzle game board: the pieces still move in the DOM, but now new clues, scores, inventory, or recommendations can arrive from an API while the player keeps playing.

In this lesson, you will learn how to:

  • Request data with fetch()
  • Read JSON responses
  • Recognize request and response parts
  • Handle network and HTTP failures separately
  • Connect fetched data back to UI rendering decisions

From DOM To Data

AJAX Mental Model

AJAX is a pattern, not one method

AJAX stands for Asynchronous JavaScript and XML, but modern AJAX usually means:

JavaScript asks a server for data without navigating away from the current page.

Despite the old name, the data is often JSON, not XML.

A typical flow looks like this:

User clicks button
      ↓
JavaScript starts request
      ↓
Browser keeps page usable
      ↓
Server sends response
      ↓
JavaScript updates state / DOM

The important shift from the previous lesson is timing. DOM changes were immediate. Network data arrives later, so your code must be organized around eventual completion.

For staff-level frontend interviews, this is not just syntax trivia. You are expected to reason about loading states, failure paths, retries, caching, and what the user sees while the request is in flight.

AJAX Mental Model

First Fetch

fetch() returns a Promise

Calling fetch(url) starts a request and gives you a Promise for a Response object.

The response body is not automatically parsed. If the API returns JSON, call response.json(), which also returns a Promise.

This example uses a data: URL so it can run without relying on an external service.

```javascript
var payload = {
  title: "Puzzle Box",
  score: 42
};

var url = "data:application/json," + encodeURIComponent(JSON.stringify(payload));

fetch(url)
  .then(function(response) {
    console.log("Status:", response.status);

    if (!response.ok) {
      throw new Error("HTTP error: " + response.status);
    }

    return response.json();
  })
  .then(function(data) {
    console.log(data.title + " score:", data.score);
  })
  .catch(function(error) {
    console.log("Fetch failed:", error.message);
  });
```

Parsing JSON

When you call response.json() in a Fetch chain, what do you get back?

HTTP Shape

Requests and responses have shape

Fetch is easier when you picture the browser and server exchanging structured messages.

A request commonly includes:

  • URL: where the request goes
  • Method: what kind of action, such as GET or POST
  • Headers: metadata, such as content type or auth information
  • Body: optional data sent to the server

A response commonly includes:

  • Status code: 200, 404, 500, etc.
  • Headers: response metadata
  • Body: often JSON, HTML, text, or a file

Common methods:

Method Usually means GET Read data POST Create or submit data PUT / PATCH Update data DELETE Remove data

This is the contract between frontend and backend. Your UI is only as reliable as your handling of that contract.

HTTP Shape

Failures Are Different

Network failure is not the same as HTTP failure

This is one of the most important Fetch details:

  • fetch() rejects when the browser cannot complete the request, such as no network, blocked request, or invalid URL.
  • fetch() usually does not reject just because the server returns 404 or 500.

For HTTP error statuses, check response.ok or response.status yourself.

A good frontend treats these as different product states. A dating-show recap app with no internet, a missing episode, and a server outage should not all show the same vague error.

```javascript
function requireOk(response) {
  if (!response.ok) {
    throw new Error("HTTP " + response.status + " " + response.statusText);
  }

  return response;
}

var fakeNotFound = new Response(
  JSON.stringify({ message: "Episode not found" }),
  {
    status: 404,
    statusText: "Not Found",
    headers: { "Content-Type": "application/json" }
  }
);

Promise.resolve(fakeNotFound)
  .then(requireOk)
  .then(function(response) {
    return response.json();
  })
  .then(function(data) {
    console.log("Data:", data);
  })
  .catch(function(error) {
    console.log("Handled:", error.message);
  });
```

CORS Control

True or false: A frontend can bypass CORS by adding an Access-Control-Allow-Origin header to its own fetch() request.

Data To Markup

Fetch gets data; your UI still decides presentation

After data arrives, you usually transform it into something the page can show.

Because you already covered DOM updates, focus here on the boundary:

  1. Fetch data
  2. Validate or shape it
  3. Render it into the UI

In production, you would also show a loading state before the data arrives and an error state if it fails.

```javascript
var recommendations = [
  { id: 1, title: "The Last Puzzle" },
  { id: 2, title: "Action Movie Night" },
  { id: 3, title: "Reality TV Strategy Guide" }
];

var url = "data:application/json," + encodeURIComponent(JSON.stringify(recommendations));

function renderList(items) {
  return items
    .map(function(item) {
      return "<li data-id=\"" + item.id + "\">" + item.title + "</li>";
    })
    .join("\n");
}

fetch(url)
  .then(function(response) {
    return response.json();
  })
  .then(function(items) {
    var html = "<ul>\n" + renderList(items) + "\n</ul>";
    console.log(html);
  });
```

The Ok Property

In Fetch, the boolean property that is true for HTTP status codes in the 200–299 range is response.____.

Type only the missing property name.

Sending JSON

Sending data uses options

fetch() accepts a second argument: an options object.

That is where you specify the method, headers, and body.

For JSON APIs, the common pattern is:

  • method: "POST"
  • Content-Type: application/json
  • body: JSON.stringify(data)

The example below builds a request object and logs what would be sent. This keeps the code runnable without depending on a real backend.

```javascript
var move = {
  player: "Ada",
  action: "unlock-door",
  room: "library"
};

var request = new Request("https://game.example/api/moves", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(move)
});

console.log("Method:", request.method);
console.log("Content-Type:", request.headers.get("Content-Type"));

request.clone().text().then(function(body) {
  console.log("Body:", body);
});
```

Fetch Checklist

Practical Fetch checklist

When you review or write frontend data-loading code, ask:

  • What starts the request? Page load, click, form submit, route change?
  • What does the user see while waiting? Empty UI, skeleton, spinner, disabled button?
  • How is the response parsed? JSON, text, blob, stream?
  • Are HTTP errors handled? Check response.ok or response.status.
  • Are network errors handled? Use .catch() for failed requests.
  • Can the request be repeated safely? Important for retries and double-clicks.
  • What owns rendering? Keep the fetch boundary separate from DOM update decisions when possible.

This is the bridge between JavaScript fundamentals and real frontend applications. Next, you will sharpen your modern JavaScript vocabulary so this kind of code becomes cleaner and more expressive.

Fetch Checklist

Open interactive view →