DEV Community

Rodrigo Castilho
Rodrigo Castilho

Posted on • Updated on

Fetch API — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle

Fetch API

Before this article, I mentioned that I would start the articles series and already created an Introduction, V8 JavaScript engine, Callbacks, AJAX and XMLHttpRequest, Synchronous and Asynchronous, Promises, and Async/Await. If you lost what I did, check it:

The Fetch API is a replacement for the older XMLHttpRequest (XHR) API, which is more complex to use and has some limitations, is simpler and more intuitive to use, and supports a wider range of data formats. Based on promises, which makes it easy to write asynchronous code that’s easy to read and understand. Promises allow developers to handle responses in a more elegant and efficient way compared to traditional callbacks.

With the Fetch API, you can initiate requests to retrieve data such as JSON, XML, HTML, or binary content like images or audio files.

One of the key benefits of the Fetch API is its use of promises, then when you make a request using the Fetch API, it returns a promise that resolves to the server’s response and this allows you to use the promise’s .then() method to handle the successful response and the .catch() method to handle any errors that may occur and also async/await syntax provides a more concise and synchronous-looking way to handle promises.

Both approaches promises with .then()/.catch() and async/await, are valid ways to handle asynchronous requests with the Fetch API. async/await can often result in more readable and concise code, especially when multiple asynchronous operations need to be chained together.

The fetch() function

It is used to initiate an HTTP request and returns a Promise that resolves to the response object representing the response to that request.

The fetch() function returns a promise that resolves the response from the server, and the response contains information such as status, headers, and actual data.

Request

The first parameter of the fetch() function is “required” and it should be either a URL string or a Request object.

The second parameter of the fetch() function is the “optional” *options *parameter that can be customized.

Some commonly used options include:

method: Specifies the HTTP method for the request (e.g., GET, POST, PUT, DELETE).

Here’s an example of using fetch() with different HTTP methods:

  • GET: The GET method is used to retrieve data from a server.

  • POST: The POST method is used to submit data to the server to create a new resource.

  • PUT: The PUT method is used to update an existing resource on the server.

  • DELETE: The DELETE method is used to delete a resource on the server.

  • PATCH: The PATCH method is used to partially update an existing resource on the server.

  • OPTIONS: The OPTIONS method is used to retrieve the supported methods and other information about a resource from the server.

  • HEAD: The HEAD method is similar to the GET method, but it retrieves only the response headers and not the response body.

headers: Allows you to set custom headers for the request, such as Content-Type or Authorization.

body: Represents the request body for methods like POST or PUT. It can be a FormData object, a plain text string, or a JSON object.

mode: Controls the request’s CORS (Cross-Origin Resource Sharing) behavior.

cache: Specifies how the browser handles caching of the response.

signal: An AbortSignal object instance; allows you to communicate with a fetch request and abort it if desired via an AbortController.

Sending Cookies and Authentication

By default, the Fetch API does not send cookies or include authentication information. To include cookies or authentication headers, you need to set the credentials option to include. This allows you to make authenticated requests or maintain session-based authentication.

Cross-Origin Requests and CORS

CORS is a security mechanism that restricts which resources a web page can request from a different domain. You need to ensure that the server supports CORS and includes the appropriate headers (e.g., Access-Control-Allow-Origin) to allow your origin to access the resource.

Response

Once you receive the response, you can process it in various ways. Common methods available on the response object include:

response.json(): Parses the response body as JSON and returns a promise that resolves to a JavaScript object.

response.text(): Returns a promise that resolves to the response body as plain text.

response.blob(): Returns a promise that resolves to a Blob object representing the response body.

*response.arrayBuffer(): *Returns a promise that resolves to an ArrayBuffer representing the response body.

You can chain these methods together to handle the response in the desired format.

Request/Response

By default, the fetch() method uses the GET method and does not include a request body. If you need to use another HTTP method or include data with the request, you’ll need to provide those details in the options object.

In the examples below, I’m using the POST method the JSONPlaceholder which is a free API whenever you need some fake data for testing and prototyping.

Important: resource will not be really updated on the server but it will be faked as if.

Using options object parameter directly:

    // Configurations for the request options directly.
    fetch("https://jsonplaceholder.typicode.com/posts", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "foo",
        body: "bar",
        userId: 1,
      }),
    })
      .then((response) => response.json())
      .then((result) => console.log(result))
      .catch((error) => console.error(error));
Enter fullscreen mode Exit fullscreen mode

Separating Headers and Body:

    // JSON object is created to define the headers.
    const headers = {
      "Content-Type": "application/json",
    };

    // JSON object and converting it to a string of body.
    const body = JSON.stringify({
      title: "foo",
      body: "bar",
      userId: 1,
    });

    const requestOptions = {
      method: "POST",
      headers,
      body,
    };

    fetch("https://jsonplaceholder.typicode.com/posts", requestOptions)
      .then((response) => response.json())
      .then((result) => console.log(result))
      .catch((error) => console.log("error", error));
Enter fullscreen mode Exit fullscreen mode

Separating Headers (using Headers() constructor) and Body:

    // headers object is created using the new Headers() constructor.
    const headers = new Headers();
    headers.append("Content-Type", "application/json");

    // JSON object and converting it to a string of body.
    const body = JSON.stringify({
      title: "foo",
      body: "bar",
      userId: 1,
    });

    const requestOptions = {
      method: "POST",
      headers,
      body,
    };

    fetch("https://jsonplaceholder.typicode.com/posts", requestOptions)
      .then((response) => response.json())
      .then((result) => console.log(result))
      .catch((error) => console.log("error", error));
Enter fullscreen mode Exit fullscreen mode

Separating Body (using FormData() constructor):

    // body object is created using the new FormData() constructor.
    const body = new FormData();
    body.append("title", "foo");
    body.append("body", "bar");
    body.append("userId", 1);

    const requestOptions = {
      method: "POST",
      body,
    };

    fetch("https://jsonplaceholder.typicode.com/posts", requestOptions)
      .then((response) => response.json())
      .then((result) => console.log(result))
      .catch((error) => console.log("error", error));
Enter fullscreen mode Exit fullscreen mode

If you need to upload files, use the FormData object to construct the request body.

Separating Method, Headers, and Body (using Request() constructor):

    // request object is created using the new Request() constructor.
    const request = new Request("https://jsonplaceholder.typicode.com/posts", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "foo",
        body: "bar",
        userId: 1,
      }),
    });

    fetch(request)
      .then((response) => response.json())
      .then((result) => console.log(result))
      .catch((error) => console.error(error));
Enter fullscreen mode Exit fullscreen mode

Setting Timeouts (using AbortController() constructor):

    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000);

    fetch("https://jsonplaceholder.typicode.com/posts", {
      signal: controller.signal,
    })
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((error) => console.error(error))
      .finally(() => clearTimeout(timeout));
Enter fullscreen mode Exit fullscreen mode

Fetching and parsing HTML content

In addition to Fetch API, you can also fetch HTML content and parse it using DOMParser() constructor manipulation techniques.

    fetch("https://rodrigocastilho.com/")
      .then((response) => response.text())
      .then((html) => {
        // DOMParser object is created using the DOMParser() constructor.
        const parser = new DOMParser();

        const doc = parser.parseFromString(html, "text/html");

        // Use DOM manipulation to extract information from the HTML
        const title = doc.querySelector("title").textContent;

        console.log(title); // Output: Rodrigo Castilho (RODCAST)
      })
      .catch((error) => console.error(error));
Enter fullscreen mode Exit fullscreen mode

Pay attention to performance considerations when working with fetch. Optimize your requests by reducing unnecessary headers, minimizing payload size, utilizing HTTP caching, and implementing proper caching strategies on the client and server side.

While the Fetch API is a powerful and flexible tool, it may not be suitable for all use cases. For more complex scenarios such as handling file uploads, WebSocket connections, or server-sent events, developers may need to use other technologies or libraries.

Thank you for reading, I hope this article can somehow have increased your knowledge base about it.

Top comments (0)