← Back to JavaScript series
🌐
Browser APIs
Advanced Β· Prerequisite: 20_Async_Basics

21. Fetch and JSON

Fetch is the HTTP client built into the browser (and Node 18+). It returns a Promise.

fetchJSONAPIasync
Duration
⏱ ~1.5 hours
Level
πŸ“Š Intermediate
Prerequisite
🎯 Lecture 20
OUTCOME
Fetch is the HTTP client built into the browser (and Node 18+). It returns a Promise.

What you'll learn

  • 1Send HTTP requests with `fetch()`.
  • 2Convert between JSON strings and JS objects.
  • 3Tell network errors apart from HTTP errors.
  • 4Rewrite fetch code with `async/await`.

Overview

Fetch is the HTTP client built into the browser (and Node 18+). It returns a Promise.

Core Concepts

1. What is fetch?

Fetch is the HTTP client built into the browser (and Node 18+). It returns a Promise.

javascript
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then((res) => res.json())
  .then((user) => console.log(user.name));

`res.json()` parses the response body as JSON and returns another Promise.

2. JSON.parse / JSON.stringify

JSON is a text-based data format β€” use these to convert to and from JS objects.

javascript
const obj = { name: 'Yi Sunshin', age: 35 };
const str = JSON.stringify(obj);   // '{"name":"Yi Sunshin","age":35}'
const back = JSON.parse(str);      // { name: 'Yi Sunshin', age: 35 }

3. POST requests

javascript
fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ title: 'hi', body: 'hello', userId: 1 }),
}).then((res) => res.json());

4. Error handling

`fetch` does not reject on 4xx/5xx. You must check `res.ok` yourself.

javascript
fetch(url)
  .then((res) => {
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return res.json();
  })
  .catch((err) => console.error('failed:', err));

A genuine network failure does reject.

5. Rewriting with async/await

javascript
async function loadUser(id) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

Examples

FileWhat it covers
01_get_json.jsGET request and JSON parsing
02_post_json.jsPOST a JSON body
03_error_handling.jsres.ok and try/catch
04_async_await.jsRewrite with async/await

src/01_get_json.js

javascript
/**
 * GET JSON data
 */
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then((res) => res.json())
  .then((user) => {
    console.log('name:', user.name);
    console.log('email:', user.email);
  });

src/02_post_json.js

javascript
/**
 * POST a JSON body
 */
const newPost = {
  title: 'hi fetch',
  body: 'body content',
  userId: 1,
};

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(newPost),
})
  .then((res) => res.json())
  .then((created) => console.log('created:', created));

src/03_error_handling.js

javascript
/**
 * fetch error handling: res.ok plus catch
 */
fetch('https://jsonplaceholder.typicode.com/users/9999')
  .then((res) => {
    if (!res.ok) {
      throw new Error(`HTTP ${res.status}`);
    }
    return res.json();
  })
  .then((data) => console.log(data))
  .catch((err) => console.error('failed:', err.message));

src/04_async_await.js

javascript
/**
 * Rewritten with async/await
 */
async function loadUser(id) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

(async () => {
  try {
    const user = await loadUser(2);
    console.log(user.name);
  } catch (err) {
    console.error(err);
  }
})();

Common Mistakes

  1. Forgetting to call `res.json()` and using the response object directly.
  2. Treating a 4xx response as success β€” you must check `res.ok`.
  3. Omitting the `Content-Type` header in a POST.
  4. Passing an object as `body` instead of `JSON.stringify(...)`.
  5. Using `await` outside an `async` function.

FAQ

Q1. Does fetch work in Node?

Yes, globally since Node 18. **Q2. Should I still use XMLHttpRequest?** A. Only for legacy compatibility β€” new code uses fetch. **Q3. Why am I seeing CORS errors?** A. The remote server must allow your origin β€” this is a server-side configuration issue.

Practice

Fetch users/posts from JSONPlaceholder and render them on the page.

homework/README.md

## Homework 1 β€” Fetch every user from `https://jsonplaceholder.typicode.com/users` and print only the names. Use async/await.

## Homework 2 β€” On an HTML page, fetch one post when a button is clicked and render it.

  • Endpoint: `https://jsonplaceholder.typicode.com/posts/1`
  • Render with `<h2>` for title and `<p>` for body.

homework/answer/homework_01.js

javascript
/**
 * Homework 1: print user names
 */
async function listUserNames() {
  const res = await fetch('https://jsonplaceholder.typicode.com/users');
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const users = await res.json();
  users.forEach((u) => console.log(u.name));
}

listUserNames().catch((err) => console.error(err));

homework/answer/homework_02.html

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Homework 2 β€” Fetch a post</title>
  </head>
  <body>
    <button id="load">Load post</button>
    <div id="result"></div>
    <script src="homework_02.js"></script>
  </body>
</html>

homework/answer/homework_02.js

javascript
/**
 * Homework 2: fetch a post on click
 */
document.getElementById('load').addEventListener('click', async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  if (!res.ok) {
    alert(`HTTP ${res.status}`);
    return;
  }
  const post = await res.json();
  const box = document.getElementById('result');
  box.innerHTML = '';
  const h2 = document.createElement('h2');
  h2.textContent = post.title;
  const p = document.createElement('p');
  p.textContent = post.body;
  box.append(h2, p);
});

Next Lecture

[22_Storage](../22_μ €μž₯μ†Œ/)

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—