Understanding Fetch() in JavaScript
The fetch()
method allows you to make network requests similar to XMLHttpRequest (XHR).
The main difference between the Fetch API and XMLHttpRequest which was otherwise known as XHR is that the Fetch API uses Promises, which makes you write cleaner API calls, strictly avoiding callback hell and reducing the complexity of XMLHttpRequest.
Basic Fetch Request
Before we experiment with an API call using fetch, let’s check out how XMLHttpRequest looks like.
Using XMLHttpRequest
We will use the famous https://jsonplaceholder.typicode.com
for our API calls.The XMLHttpRequest
needs two listeners to be set to handle the success response and error response cases and a call to open()
and send()
.
function getAllPosts() {
let data = JSON.parse(this.responseText);
console.log(data);
}
let reqError = err => {
console.log("Error", err);
};
let req = new XMLHttpRequest();
req.onload = getAllPosts;
req.onerror = reqError;
req.open("GET", "https://jsonplaceholder.typicode.com/posts", true); //here you are specifing that this is a get request and its calling that URL.
req.send();
Using Fetch
Now take a look at the Beauty of Fetch. Let’s rewrite the code above using Fetch. There are many ways we could use the fetch method, we could use the then method or we use async/await method. Let’s see how we can do this.
Using Async/Await method
Using the try/catch
constructor, async/await
makes it relatively easy to handle both synchronous and asynchronous errors:
async function getAllPosts() {
try {
let response = await
fetch("https://jsonplaceholder.typicode.com/posts" );
const data = await response.json();
console.log(data);
} catch (err) {
console.log(err);
}
}
Using The Then Method
Using this method isn’t bad at all but however, the chaining of .then()’s can lead to what is often referred to as callback hell, or nested callbacks, that quickly reduce readability and can easily lead to bad performance or bugs.
function getAllPosts() {
fetch("https://jsonplaceholder.typicode.com/posts")
.then(response => response.json())
.then(data => { console.log(data)})
.catch(err => {console.log(err);
});
}
Basic Response Types
When we make a fetch request, the response is given a type of CORS
, opaque
or basic
. These response types indicate where the resource is coming from and this also allows you to know how to handle the response.
Ok let me explain these types:
When a request is made from the same origin, the response will have a basic type and there aren’t any restrictions on what you can view from the response.
If a request is made from another origin, the response will have a CORS
type. CORS
and basic
response type is almost identical except that a CORS response restricts the headers you can view to Cache-Control, Content-Language
, Content-Type
, Expires
and Last-Modified
.
An opaque
response is for a request made from a resource on a different origin that doesn’t return CORS headers. This type of response won’t let you read the data returned or view the status of the request, meaning you can’t check if the request was successful or not.
Making A Post Request with FETCH
We could use the Fetch method to do other things apart from getting data from an api. Imagine we want to add a new blog post to the jsonplaceholder API, we can use the Fetch method to accomplish that too.
Let’s create a simple form for adding a new blog post.
<form id="postData">
<div>
<input type="text" name="" id="title" placeholder="Title" />
</div>
<div>
<textarea name="" id="body" cols="20" placeholder="Content" rows="5"></textarea>
</div>
<input type="submit" value="SEND POST" />
</form>
Now We have a form for adding a new blog post, let’s write a script that will send the data to the jsonplaceholder
API.
document.getElementById("postData").addEventListener("submit", addNewPost); //on submit calls a function addNewPost.
async function addNewPost(event) {
try {
event.preventDefault();
let tittle = document.getElementById("title").value; //get value of title
let body = document.getElementById("body").value; //get value of body
let response = await fetch("https://jsonplaceholder.typicode.com/posts",{
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({ tittle: tittle, body: body })
}
);
const data = await response.json();
console.log(data);
} catch (err) {
console.log(err);
}
}
Always remember to use the preventDefault() method to stop or prevents the browser from executing the default action. That’s how to make a POST request using Fetch.
Handling File upload using Fetch.
We could also handle file uploads such as images and pdfs using Fetch. Here’s how it’s done.
document.getElementById("postData").addEventListener("submit", uploadfile); //on submit calls a function uploadfile.
async function uploadfile(event) {
try {
event.preventDefault();
const fileField = document.querySelector('input[type="file"]');
const formData = new FormData();
formData.append("avatar", fileField.files[0]);
let response = await fetch("https://jsonplaceholder.typicode.com/photos",{
method: "POST",
headers: { "Content-Type": "application/json" },
body: formData
});
const data = await response.json();
console.log(data);
} catch (err) {
console.log(err);
}
}
Sending Credentials with a Fetch Request
There are situations where you want to make a fetch request with credentials such as cookies, you should set the credentials
of the request to “include
“
fetch(url, {
credentials: 'include'
});
Conclusion
While fetch
is a nicer method for making a network request, the API currently doesn’t allow for canceling a request, which makes it a non-starter for many developers.The new fetch
API seems much faster and simpler to use than XHR. After all, it was created so that we could do handle AJAX request the right way.