Javascript Fetch API Simplified

Javascript Fetch API Simplified

Learn Ajax Requests using Fetch API

History

One of the most usages of javascript is making Requests to backends using Ajax without Page Reload. The ancient way of doing request is use XMLHttpRequest API, that was just fine but requires long code and not really simple to achieve. JQuery came to solve complexity of XMLHttpRequest and provided an API to make Ajax Requests which we so popular for long period of time.

Fetch API Compared to jQuery Ajax

  • Fetch API is native to javascript, thats means it doesn't add more load to your application as jQuery do, also it makes it usable whatever JavaScript Framework you are using as it has no dependencies.
  • Fetch API Promise won't fail or reject on HTTP error response like 404 ... etc, instead it will just continue and set ok value to false, but it will only fails and reject on Network errors.
  • jQuery Ajax is just a wrapper for XMLHttpRequest so it's safer to use on very old Browsers for competabiliy but almost every modern browser now supports Fetch API.
  • Fetch API won't send Cookies by default, so some authentication processes may fail but of course you can set the cookies manually with initial options.
  • Fetch API doesn't support timeouts, which means request will keep going trying yo get response until browser decides not to. For sure you can overcome this using Promise.race() . We will learn more about this.

Getting Started

In this tutorial we going to use JSONPlaceHolder API as for demonstration purposes, it's Free and more than enough for our tutorial

Fetch API is totally native to Javascript so we don't need to add any packages or libraries, just a typical HTML document to work with

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fetch API</title>
</head>
<body>

    <script type="text/javascript">
        //Our Javascript code to be Here
    </script>
</body>
</html>

HTTP GET Request

Now we going to learn how to issue a GET request to get list of posts

EndPoint : jsonplaceholder.typicode.com/posts

//Execute one DOM Fully Loaded
document.addEventListener('DOMContentLoaded', () => {
     //GET Request -> https://jsonplaceholder.typicode.com/posts
     fetch('https://jsonplaceholder.typicode.com/posts')
         .then(response => response.json())
         .then(jsonResponse => console.log(jsonResponse));
});

Code Explainations

  • First we wrapped our code within DOMContentLoaded event to make sure code executes once Page fully loaded to avoid any further issues.
  • fetch function is used to issue ajax request, it takes 2 arguments. First argument indicates the endpoint or url you are issuing request to, second arguments is initial options where you can specify more options regarding your request and we don't use it here as we has nothing special. Note : fetch by default consider you are making a GET request unless you specify something else.
  • fetch will always return a Promise that's why we used then method to chain execution after request is done
  • After request completed we chained it with a callback to extract Response Body as Json using response.json() which also will return a Promise.
  • Finally we chained another callback to console.log the Json Response to the console.

console-log-json.png

Another Example

Let's try again to get a single post item and console.log its title

EndPoint : jsonplaceholder.typicode.com/posts/1

//Get Request -> https://jsonplaceholder.typicode.com/posts/1
fetch('https://jsonplaceholder.typicode.com/posts/1')
     .then(response => response.json())
     .then(postItem => console.log(postItem.title));

HTTP POST Request

Since we now know how to make GET requests then POST request won't be any hard, it's almost similar with only few points

  • We need to tell Fetch API that we are using POST instead of GET
  • Mostly with POST requests we need to pass Data to the request
  • Optionally some APIs requires some headers to be sent with the Request
  • Also you may need to work on APIs that requires authentication and authorization. This Points can be achieved easily using the second argument of fetch method, actually it expects an object with some options modifier, so we gonna use method and body options, Optionally : we can use headers option.

EndPoint : jsonplaceholder.typicode.com/posts

//POST Request -> https://jsonplaceholder.typicode.com/posts
fetch('https://jsonplaceholder.typicode.com/posts', {
    method: 'POST',
    //Send Data as Json String
    body: JSON.stringify({
        title: 'Fetch API',
        body: 'Ajax is Awesome using Fetch',
        userId: 1
    }),
    //Set Extra Headers
    headers: {
        'Content-type': 'application/json; charset=UTF-8',
    },
})
.then(response => response.json())
.then(newPost => console.log(newPost));

HTTP PUT Request

Its similar to POST request but we set method option to PUT, PUT Requests usually used to update a resources.

EndPoint : jsonplaceholder.typicode.com/posts/1

//PUT Request -> https://jsonplaceholder.typicode.com/posts/1
fetch('https://jsonplaceholder.typicode.com/posts/1', {
        method: 'PUT',
        //Send Data as Json String
        body: JSON.stringify({
            title: 'Fetch API is Excellent',
        }),
        //Set Extra Headers
        headers: {
             'Content-type': 'application/json; charset=UTF-8',
        },
    })
    .then(response => response.json())
    .then(updatedPost => console.log(updatedPost));

HTTP DELETE Request

DELETE Request is usually used to delete a resource on server

EndPoint : jsonplaceholder.typicode.com/posts/1

//DELETE Request -> https://jsonplaceholder.typicode.com/posts/1
fetch('https://jsonplaceholder.typicode.com/posts/1', {
        method: 'DELETE',
    })
    .then(response => response.json())
    .then(jsonResponse => console.log(jsonResponse));

Extra Bonus

Now since we can work well with Fetch API it's time for some bonus tips and tricks

Timeouts

As we said before Fetch doesn't support timeouts , so how we can handle timeouts ? Well it's totally simple since fetch return a Promise so we can use race .

//GET Request -> https://jsonplaceholder.typicode.com/posts/1
Promise.race([
        fetch('https://jsonplaceholder.typicode.com/posts/1'),
        new Promise((resolve, reject) => {
            setTimeout(() => reject(new Error('Request Timeout')), 3000);
         })
    ])
    .then(response => response.json())
    .then(postItem => console.log(postItem.title))
    .catch((error) => console.log(error));

Final Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fetch API</title>
</head>
<body>
    <script type="text/javascript">
        //Execute one DOM Fully Loaded
        document.addEventListener('DOMContentLoaded', () => {

            //Example .1
            /** Get List of Posts
            //GET Request -> https://jsonplaceholder.typicode.com/posts
            fetch('https://jsonplaceholder.typicode.com/posts')
                .then(response => response.json())
                .then(jsonResponse => console.log(jsonResponse));
            */

            //Example .2
            /** Get Single Post Item
            //Get Request -> https://jsonplaceholder.typicode.com/posts/1
            fetch('https://jsonplaceholder.typicode.com/posts/1')
                .then(response => response.json())
                .then(postItem => console.log(postItem.title));
            */

            //Example .3
            /** Create new Post
            //POST Request -> https://jsonplaceholder.typicode.com/posts
            fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                //Send Data as Json String
                body: JSON.stringify({
                    title: 'Fetch API',
                    body: 'Ajax is Awesome using Fetch',
                    userId: 1
                }),
                //Set Extra Headers
                headers: {
                    'Content-type': 'application/json; charset=UTF-8',
                },
            })
            .then(response => response.json())
            .then(newPost => console.log(newPost));
            */

            //Example .4
            /** Update Existing Post
            //PUT Request -> https://jsonplaceholder.typicode.com/posts/1
            fetch('https://jsonplaceholder.typicode.com/posts/1', {
                method: 'PUT',
                //Send Data as Json String
                body: JSON.stringify({
                    title: 'Fetch API is Excellent',
                }),
                //Set Extra Headers
                headers: {
                    'Content-type': 'application/json; charset=UTF-8',
                },
            })
            .then(response => response.json())
            .then(updatedPost => console.log(updatedPost));
            */

            //Example .5
            /** Delete Existing Post
            //DELETE Request -> https://jsonplaceholder.typicode.com/posts/1
            fetch('https://jsonplaceholder.typicode.com/posts/1', {
                method: 'DELETE',
            })
            .then(response => response.json())
            .then(updatedPost => console.log(updatedPost));
            */

            //Bonus .1
            /** Get a Post with timeout of 3 seconds
            //GET Request -> https://jsonplaceholder.typicode.com/posts/1
            Promise.race([
                fetch('https://jsonplaceholder.typicode.com/posts/1'),
                new Promise((resolve, reject) => {
                    setTimeout(() => reject(new Error('Request Timeout')), 3000);
                })
            ])
            .then(response => response.json())
            .then(postItem => console.log(postItem.title))
            .catch((error) => console.log(error));
            */

        });
    </script>
</body>
</html>