DEV Community

Cover image for Fetch API and HTTP requests in JavaScript
JanetMutua
JanetMutua

Posted on • Edited on

Fetch API and HTTP requests in JavaScript

TL;DR

A simple guide on using the Fetch API to make network requests in JavaScript. Learn how to use async/await to make your code more readable. See how you can handle errors gracefully to avoid your program crashing.

Introduction

If you want a clean and flexible way to handle network requests, then the Fetch API comes in handy. The Fetch API is a modern JavaScript interface for making asynchronous HTTP requests to servers. You use promises to fetch resources from servers asynchronously.

Promises, as we will see later in this tutorial, help make your code more readable and maintainable as opposed to callback approaches.

Fetch API replaces older methods like:

  • XML HttpRequest
  • jQuery’s AJAX methods

Prerequisites

To proceed with this guide, you need a basic understanding of:

  • Core JavaScript basics like:
    • Arrow functions
    • Objects
    • String manipulation with template literals
  • Asynchronous concepts like:
    • Promises (.then() and .catch())
    • Async/await syntax
  • HTTP and networking basics, such as:
    • HTTP methods (GET and POST)
    • Status codes
    • Basic API understanding

I will provide brief explanations of these concepts whenever necessary.

Understanding Fetch API Syntax

Before we dive into the various use cases of the Fetch API, let’s first get a rundown of the syntax.

fetch(url)
 .then(response => response.json()) // parses the response body to JSON
 .then(data => console.log(data)) // logs the data into the console
 .catch(error => console.error(error)); // catches errors if request fails

Enter fullscreen mode Exit fullscreen mode

The fetch() function takes a URL as an argument and sends requests to that URL. The default request is usually a GET request. You can supply an optional second argument as an object to specify a HTTP method, or headers in the case of a POST request.

.then() handles responses when the request is successful. You parse the response body to JSON and later log the data received.

.catch() catches errors like network issues and invalid responses, in cases where the request fails. However, .catch() doesn’t throw errors for HTTP status codes like 404.

We shall see later in this guide how to handle 404 errors manually using the reponse.ok.

Handling HTTP Requests

Handling HTTP Requests(Source: Gemini)

When making a GET request using fetch(url), your code returns a Promise that resolves into a Response object.

Let’s take a look at a simple GET Request.

GET Request

To illustrate a GET request, we will use a fun example of a free API resource that generates random sentences to make you sound tech-savvy. You can generate as many random messages as you want with the API.

You start by adding the API endpoint as an argument to fetch() and use .then() and .catch() promises to define what happens to the response body.

Before parsing data into JSON, you should first check if the response was successful using response.ok.

Once successful, the code proceeds on to parse the response body into JSON and log the data to the console. The .catch() block is there to handle any network errors or invalid responses.

fetch("https://techy-api.vercel.app/api/json")
    .then(response => {
        // Check if response is successful
        if (!response.ok) {
            throw new Error(`Network error! Status: ${response.status}`);
        }
        return response.json(); // parse the response body into JSON
    })
    .then(data => console.log(data)) // log data to the console
    .catch(error => console.error("Error:", error)); // handle errors when request fails
Enter fullscreen mode Exit fullscreen mode


The result is a random message as shown above.

POST Request

To make a POST, PUT, or DELETE request, you have to provide an options object that specifies the method, headers, and body as needed.

Query Parameters

When working with APIs, adding parameters helps you filter or modify the data you receive. Now let’s see how we can manipulate query parameters for API endpoints.

We will use the Faker API to generate random addresses for any country of our choice. Take a look at the code below:

// Initializing the API endpoint
const apiUrl = "https://fakerapi.it/api/v2/addresses?_quantity=1";

// Initializing a query parameter
const queryParam = {
  _country_code: "en_CA",
};

// Converting query parameter to string
const queryStr = new URLSearchParams(queryParam).toString();

// API endpoint + query parameter
const addressUrl = `${apiUrl}&${queryStr}`;

fetch(addressUrl)
  .then(response => {
    if (!response.ok) {
      throw new Error(`Network error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(address => console.log(address))
  .catch(error => console.error("Error:", error));

Enter fullscreen mode Exit fullscreen mode

The result looks like this:


The example above shows a dummy address generated from the Faker API filtered for the Canada region.

Using async/await with the Fetch API

Async/await lets you simplify asynchronous operations using promises. The async function ensures the execution thread is not blocked, while the await block pauses execution until a promise is returned.

 (Source: Gemini)

We will still use Faker API to demonstrate how you can add async/await when making network requests. In the code below, we will create an async function fetchAddress to help us generate random addresses from an API.

// Initializing the API endpoint
const apiUrl = "https://fakerapi.it/api/v2/addresses?_quantity=1";

// Initializing a query parameter and convering it to string
const queryParam = {
  _country_code: "en_CA",
};

const queryStr = new URLSearchParams(queryParam).toString();

// API endpoint + query parameter
const addressUrl = `${apiUrl}&${queryStr}`;

async function fetchAddress() {
  try {
    const response = await fetch(addressUrl);
    // Check if response is successful
    if (!response.ok) {
      throw new Error(`Network error. Status: ${response.status}`);
    }
    const addressData = await response.json();
    console.log(addressData);
  } catch (error) {
    console.error("Error:", error);
  }
}

fetchAddress();
Enter fullscreen mode Exit fullscreen mode

The result is a randomly generated address as shown below:


Using await fetch(addressUrl); removes the need to add multiple .then() methods.

Also, the await response.json(); pauses code execution until the response body is parsed to JSON.

Error Handling

 (Source: Gemini)

Checking for errors when fetching data helps you identify potential issues that may make your app crash. The try/catch block helps identify any errors when fetching requests and parsing the response. However, some HTTP error codes require you to log them manually.

Here’s a recap of how we can catch errors in various sections of our code:


So, how exactly does each code block help catch errors?

  1. The if(!response.ok) code block checks for response status in the 200 to 299 range; otherwise, it logs an error.
  2. The throw new Error(); logs a custom message when the response fails.
  3. The catch() block handles invalid responses and network issues.

Conclusion

In this article, we have covered key concepts on using the Fetch API to make network requests. We have also seen how to use async/await to make code more readable, and how to handle errors using try/catch and response.ok.

I hope this article has been of help to you.

Follow me on Hashnode and Medium for more tutorials and guides.

Keep building! 🌟

References

  1. Using the Fetch API
  2. Promise
  3. Fetch
  4. How To Use JavaScript Fetch API To Get Data?

Top comments (0)