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.
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>