Fetch API
Tags: javascript, asynchronous, fetch, promise
Published: 2023-10-09 00:27:50


***Fetch API*** - One of the requirements for my phase-5 capstone project with FlatIron School was to write a technical blog. I could'nt decide what to write about since the list of topics seemed endless. However, as I began to develop my app, I found myself running into problems with handling responses coming Fetch API. It didn't take long for me to  realize I didn't understand how it worked. I knew there was something called the **promise** and it had something to do with **response ojects** being return and **.then()** running aftwards, but I was just fudging my way through, throwing code and the wall and seeing what stuck so to speak. I found I was taking so much time working through those errors that it chewed up precious time better spent writing and perfecting functionality. Hence, **The Promise...*****Then***

***Fetch API***
Fetch API is an interface to getting or *fetching* resources. Fetch() requires one argument which is the path to the resource you want to fetch. It's a powerful way to make HTTP request in Javascript. 

***Promises:*** 
A promise is an JavaScript object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

A Promise may have one of three states:
- *Pending*: The initial state; neither filled nor rejected.
- *Fulfilled* : The operation completed sucessfully and the resulting value is available
- *Rejected*: The operation failed, and an error reason is available. 

A promise starts in a *pending* state. That means the process is not complete. If the operation is successful, the process ends in a *fulfilled* state. And, if an error occurs, the process ends in a *rejected* state.

For example, when you request data from the server by using a promise, it will be in a pending state. When the data arrives successfully, it will be in a fulfilled state. If an error occurs, then it will be in a rejected state. You can attach callbacks to a Promise using the .then() and .catch() methods. The ***.then() method is called when the Promise is fulfilled, while the .catch() method is called when the Promise is rejected.***

In my research I found there's alot that can be said about promises. You can actually create them but that's beyond the scope of this blog. Right now I want to discuss how to make use of them in conjunction with Fetch API!!! ***So let's get to it!!!***

***Using the Fetch API***
The Fetch API really is simple to use. You call fetch() and provide the url of the resource you're trying to fetch. The fetch() returns a promise that resovles to a response object. 

```
fetch('https://api.example.com/data')
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });
```
In the example above, we are fetching data from https://api.example.com/data. The fetch() method returns a *Promise*(* in the fulfilled state that resovles to a response*), and we are using the .then() method to handle the successful response and the .catch() method to handle any errors.

The Response object that we receive in the .then(*response*) method contains several properties and methods that can be used to extract the data from the response object. Some of the most commonly used properties and methods are as follows:

- ***response.ok:*** A boolean value that indicates whether the request was successful (status code in the range 200-299) or not.
- ***response.status:*** The status code of the response (e.g., 200, 404, 500, etc.).
- ***response.statusText:*** A status message corresponding to the status code (e.g., "OK", "Not Found", "Internal Server Error", etc.).
- ***response.headers:*** An object representing the headers of the response.
- ***response.json():*** A method that returns a Promise that resolves to the JSON object resulting from parsing the response's body text as JSON.
- ***response.text():*** A method that returns a Promise that resolves to the response's body text as a string.

```
        fetch(`/dancers/${values["email"]}?action=none`)
        .then(res => {
            if (!res.ok){ 
                throw new Error('Network response was not ok');
             }
             return Response.json() //Returns a promise that resolves to Json data
            })    
        .then((dancer) => {     
            setDancer(dancer)
            handleShowDancer()
        }) 
        .catch(error => {
            console.log("Error Returned",error);    
            // onError(error) 
            setError(error)
        })
    }

```
In this example (*using code from my app*), we first check if the response.ok property is true. If it is not, we throw an error that will be caught by the .catch() method. Otherwise, we call the response.json() method, which returns a Promise that resolves to a response that is then resolved to the JSON data. We then use another .then() method to handle the JSON data.  

The idea that we can fetch data in other formats, like text and binary data(images, audio, files etc) also intrigued me. 

```
fetch('https://api.example.com/data.txt')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.text(); // text instead of json
  })
  .then(text => {
    console.log(text);
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });
```
Fetch with Async/Await
Another technique I've been very curious about is Async/Await. This is another way I've seen the fetch method used. According to the documentation I just read we:

1. Declare an async function. This tells JavaScript that the  function will contain asynchronous code.
2. Inside the async function, use the await keyword before calling the fetch() method. This tells JavaScript to wait for the Promise to resolve before continuing with the rest of the code.
3. Use try/catch blocks to handle errors.

```
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
}

fetchData();
```
So we declare an async function called fetchData. Inside the function, we use the **await** keyword before calling the fetch() method and the response.json. 

Giselle Smith is a FullStack Software Developer Engineer student at [Flatiron School](https://flatironschool.com/)

References:
[Asynchronous JavaScript for Beginners](https://semaphoreci.com/blog/asynchronous-javascript#:~:text=Asynchronicity%20means%20that%20if%20JavaScript,callback%20queue%20and%20event%20loop.)
[How to use promises](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises)
https://www.altcademy.com/blog/how-to-use-the-javascript-fetch-api-to-get-data/