DEV Community

Cover image for The Fetch API (With async/await)
Monicah Ajeso
Monicah Ajeso

Posted on

The Fetch API (With async/await)

What is the Fetch API?

The Fetch API is JavaScript's built-in way of making network requests — asking a server for data or sending data to one.

Every time you call fetch(), it returns a Promise (remember those?). That Promise eventually resolves with a Response object — which holds whatever the server sent back.

fetch() → Promise → Response → Your Data
Enter fullscreen mode Exit fullscreen mode

The Basic Structure

fetch("https://api.example.com/users")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.log("Error:", error));
Enter fullscreen mode Exit fullscreen mode

Two .then() calls — here's why:

  • The first .then() gets the raw Response object and converts it to JSON
  • The second .then() gives you the actual data you asked for
  • .catch() handles anything that goes wrong

💡 response.json() also returns a Promise — that's why you need the second .then()


async/await — A Cleaner Way to Write Fetch

Promises with .then() work perfectly fine, but async/await makes the same code easier to read — especially as your requests get more complex.

// With .then()
fetch("https://api.example.com/users")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.log("Error:", error));

// With async/await — same thing, cleaner look
async function getUsers() {
  try {
    const response = await fetch("https://api.example.com/users");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error:", error);
  }
}
Enter fullscreen mode Exit fullscreen mode

await tells JavaScript: "pause here and wait for this Promise to resolve before moving on."

try/catch replaces .catch() for handling errors.

💡 You can only use await inside a function marked async


GET — Fetching Data

GET is the default method — you don't even need to specify it. Use it when you want to read data from a server.

async function getUser() {
  try {
    const response = await fetch("https://api.example.com/users/1");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error:", error);
  }
}

getUser();
Enter fullscreen mode Exit fullscreen mode

Sample response:

{
  "id": 1,
  "name": "Monicah",
  "role": "developer"
}
Enter fullscreen mode Exit fullscreen mode

POST — Sending Data

POST is used when you want to create something new on the server — like submitting a form or creating an account.

This time you need to pass a second argument to fetch() — an options object that describes your request.

async function createUser() {
  try {
    const response = await fetch("https://api.example.com/users", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        name: "Monicah",
        role: "developer"
      })
    });

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error:", error);
  }
}

createUser();
Enter fullscreen mode Exit fullscreen mode

Three new things here:

  • method — tells the server what you want to do ("POST")
  • headers — tells the server you're sending JSON
  • body — the actual data you're sending, converted to a JSON string with JSON.stringify()

PUT — Replacing Data

PUT is used to replace an existing resource entirely. You're not updating one field — you're sending the full updated object.

async function updateUser() {
  try {
    const response = await fetch("https://api.example.com/users/1", {
      method: "PUT",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        name: "Monicah W",
        role: "frontend developer"
      })
    });

    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error:", error);
  }
}

updateUser();
Enter fullscreen mode Exit fullscreen mode

💡 Notice the URL — /users/1 targets a specific user. You have to tell the server which resource you're replacing.


DELETE — Removing Data

DELETE is used to remove a resource from the server. Most of the time you don't need a body — just the URL and the method.

async function deleteUser() {
  try {
    const response = await fetch("https://api.example.com/users/1", {
      method: "DELETE"
    });

    if (response.ok) {
      console.log("User deleted successfully");
    }
  } catch (error) {
    console.log("Error:", error);
  }
}

deleteUser();
Enter fullscreen mode Exit fullscreen mode

response.ok is true when the status code is between 200–299 — a quick way to check if the request succeeded.


Quick Comparison

Method Purpose Needs a body?
GET Read data No
POST Create new data Yes
PUT Replace existing data Yes
DELETE Remove data No

.then() vs async/await — Which Should You Use?

Both do the same thing. It comes down to readability:

.then() async/await
Style Chain-based Looks like regular code
Error handling .catch() try/catch
Best for Simple, single requests Multiple requests in sequence

For most real-world use cases, async/await is preferred — especially when you need to make one request that depends on the result of another.


Happy coding!!! 😊

Top comments (0)