JavaScript Fetch API
Table of Contents + โ
In the previous lesson, we learned how async and await make asynchronous code read like normal step-by-step code. Now letโs put that to work with the Fetch API, the built-in way to request data from a server.
๐ What is the Fetch API?
The Fetch API lets your code make an HTTP request to get data from a server or an API. The fetch() function takes a URL and returns a promise, so it fits the async/await pattern from the last lesson.
A server is a computer that holds data and sends it back when you ask for it. An API is the address and rules you follow to ask for that data.
fetch("https://api.example.com/users"); // returns a promiseThis one line calls fetch() with the URL we want to request, and fetch() hands back a promise instead of the data itself.
Because fetch() returns a promise, the result is not ready right away. You use await to pause until the server responds.
๐ The Two-Step Pattern
Getting data with fetch takes two awaits. The first gets the response, and the second reads the data out of it.
const response = await fetch("https://api.example.com/users"); // โ
step 1: get the responseconst data = await response.json(); // โ
step 2: read the JSON bodyLetโs walk through what each line does:
const response = await fetch(...)sends the request and waits for the serverโs reply, giving us aResponseobject that describes the reply but does not contain the data yet.const data = await response.json()reads the body of that response and turns the JSON text into a JavaScript object or array we can use.
JSON stands for JavaScript Object Notation. It is a text format for sending data, and response.json() parses that text into values you can use.
Why two awaits?
Both steps are asynchronous. Reading the response body takes time too, so
response.json() also returns a promise that you must await.
๐ฅ A GET Request with async/await
The most common request is a GET request, which asks the server for data. This function fetches a list of users from a public API and returns it.
async function getUsers() { const response = await fetch("https://jsonplaceholder.typicode.com/users"); const users = await response.json(); return users;}
const users = await getUsers();console.log(users[0].name); // the name of the first userHere is what each step does:
async function getUsers()marks the function as asynchronous so we can useawaitinside it.await fetch(...)pauses until the server replies and stores theResponseobject inresponse.await response.json()parses the body into a real array and stores it inusers.return usershands that array back to the caller.await getUsers()runs the function and waits for the array, thenconsole.log(users[0].name)prints the name of the first user.
โ Checking response.ok
A request can reach the server but still fail, for example when a page is not found. The response.ok property is true only when the status code is in the 200 range, so you check it before reading the data.
async function getUser(id) { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`); }
return await response.json();}Letโs read this line by line:
await fetch(...)builds the URL with theidand waits for the serverโs reply.if (!response.ok)checks whether the request actually succeeded;response.statusholds the numeric HTTP code, such as200for success or404for not found.throw new Error(...)stops the function with a clear message when the request failed, so you handle the problem instead of working with bad data.return await response.json()runs only when the response is good, parsing and returning the data.
Fetch does not reject on 404 or 500
fetch only rejects its promise when the network itself fails, such as no
internet connection. A 404 or 500 response is still a successful fetch, so
you must check response.ok yourself.
๐ค Sending Data with POST
A GET request reads data, while a POST request sends data to the server. You pass a second argument to fetch that sets the method, headers, and body.
const response = await fetch("https://jsonplaceholder.typicode.com/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Alex", email: "alex@example.com" }),});
const created = await response.json();The second argument is an options object, and each field tells fetch how to send the request:
method: "POST"says what kind of request to make.headers: { "Content-Type": "application/json" }tells the server you are sending JSON.body: JSON.stringify(...)is the data itself, withJSON.stringifyturning your object into the JSON text the server expects.await response.json()reads the serverโs reply, which here is the record it created.
๐ ๏ธ Fetch and Display Data
This example fetches a single post and shows its title on the page. It ties the steps together: request, check, read, then use the data.
async function showPostTitle() { const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
if (!response.ok) { throw new Error(`Request failed with status ${response.status}`); }
const post = await response.json(); document.querySelector("#title").textContent = post.title;}
showPostTitle();Here is how the pieces fit together:
await fetch(...)requests the post and waits for the reply.if (!response.ok)confirms the request succeeded before going further.const post = await response.json()reads the JSON into apostobject.document.querySelector("#title").textContent = post.titlewrites the title into the element with the idtitle.showPostTitle()calls the function so the whole sequence runs.
โ ๏ธ Common Mistakes to Avoid
| Mistake | Problem | Solution |
Forgetting the second await | response.json() returns a promise, not the data | Write await response.json() |
Not checking response.ok | A 404 or 500 is treated as success | Check response.ok before reading the body |
Forgetting fetch is async | Using the result before it arrives gives a promise | Use await inside an async function |
๐ง Try It Yourself!
- Write an
asyncfunction that fetcheshttps://jsonplaceholder.typicode.com/users. - Use the two-step pattern:
await fetch(...)thenawait response.json(). - Add an
if (!response.ok)check that throws an error. - Log the name of the first user to the console.
๐งฉ What Youโve Learned
- โ
fetch(url)makes an HTTP request and returns a promise - โ
The two-step pattern is
await fetch(url)thenawait response.json() - โ
response.oktells you whether the request actually succeeded - โ
fetchonly rejects on network failure, not on404or500 - โ
A POST request sends data with
method,headers, andbody
๐ Whatโs Next?
Now that you can request data, we will learn how to handle the things that can go wrong. Letโs continue to Error Handling.