Skip to main content

The fetch() API

The most common and vital use of Promises and Asynchrony in frontend web development is to request data from an external server (Backend) using "APIs".

For this, the browser provides us with a native tool called fetch().

What does fetch do?

fetch() always returns a Promise that will resolve to the "Response" to the HTTP request, whether successful or not.

It is almost always used in combination with the modern async / await syntax.

The classic 2-step Fetch cycle

Requesting data usually requires two chained promises:

  1. Contact the server (fetch()).
  2. Convert the text returned by the server into a manipulable JavaScript data format called JSON (response.json()).

Example: Requesting fake data

We are going to consume data from a free test API called "JSON Placeholder".

const getUsers = async () => {
const url = "https://jsonplaceholder.typicode.com/users";

try {
console.log("Connecting to the server...");
// 1. First Await: We make the network request and wait for the server's response
const response = await fetch(url);

if (!response.ok) {
// The server responded, but with an error (e.g., 404 Not Found)
throw new Error(`HTTP Error! Status: ${response.status}`);
}

console.log("Downloading data...");
// 2. Second Await: We wait for the system to process and convert the plain text response to JSON (JS objects).
const userData = await response.json();

console.log("Success!");

// userData is now a normal JavaScript Array. Let's use .map()!
userData.map(user => {
console.log(`User: ${user.name} (${user.email})`);
});

} catch (error) {
// Catches network failures (e.g., internet went down) or the manual throw above
console.error("Could not get the information:", error);
}
};

getUsers();

This is the standardized pattern for consuming data in 99% of modern web applications made with React, Vue, Angular, or pure Vanilla JS.