There was a time when XMLHttpRequest
was used to make API requests. It didn’t include Promises, and it didn’t make for clean JavaScript code. Using jQuery, you could use the cleaner syntax of jQuery.ajax()
.
Now, JavaScript has its own built-in way to make API requests. This is the Fetch API, a new standard to make server requests with Promises, but which also includes additional features.
In this tutorial, you will create both GET and POST requests using the Fetch API.
Deploy your frontend applications from GitHub using DigitalOcean App Platform. Let DigitalOcean focus on scaling your app.
To complete this tutorial, you will need the following:
One approach to using the Fetch API is by passing fetch()
the URL of the API as a parameter:
fetch(url)
The fetch()
method returns a Promise. After the fetch()
method, include the Promise method then()
:
fetch(url)
.then(function() {
// handle the response
})
If the Promise returned is resolve
, the function within the then()
method is executed. That function contains the code for handling the data received from the API.
After the then()
method, include the catch()
method:
fetch(url)
.then(function() {
// handle the response
})
.catch(function() {
// handle the error
});
The API you call using fetch()
may be down or other errors may occur. If this happens, the reject
promise will be returned. The catch
method is used to handle reject
. The code within catch()
will be executed if an error occurs when calling the API of your choice.
With an understanding of the syntax for using the Fetch API, you can now move on to using fetch()
on a real API.
The following code samples will be based on the JSONPlaceholder API. Using the API, you will get ten users and display them on the page using JavaScript. This tutorial will retrieve data from the JSONPlaceholder API and display it in list items inside the author’s list.
Begin by creating an HTML file and adding a heading and unordered list with the id
of authors
:
<h1>Authors</h1>
<ul id="authors"></ul>
Now add script
tags to the bottom of your HTML file and use a DOM selector to grab the ul
. Use getElementById
with authors
as the argument:
<h1>Authors</h1>
<ul id="authors"></ul>
<script>
const ul = document.getElementById('authors');
</script>
Remember, authors
is the id
for the previously created ul
.
Next, create a list
that is a DocumentFragment
:
<script>
// ...
const list = document.createDocumentFragment();
</script>
All the appended list items will be added to list
. A DocumentFragment
is not part of the active document tree structure. This has the benefit of not causing performance-affecting redraws when the Document Object Model is changed.
Create a constant variable called url
which will hold the API URL that will return ten random users:
<script>
// ...
const url = 'https://jsonplaceholder.typicode.com/users';
</script>
Now using the Fetch API, call the JSONPlaceholder API using fetch()
with url
as the argument:
<script>
// ...
fetch(url)
</script>
You are calling the Fetch API and passing in the URL to the JSONPlaceholder API. Then a response is received. However, the response you get is not JSON, but an object with a series of methods that can be used depending on what you want to do with the information. To convert the object returned into JSON, use the json()
method.
Add the then()
method which will contain a function with a parameter called response
:
<script>
// ...
fetch(url)
.then((response) => {})
</script>
The response
parameter takes the value of the object returned from fetch(url)
. Use the json()
method to convert response
into JSON data:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
</script>
The JSON data still needs to be processed. Add another then()
statement with a function that has an argument called data
:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {})
</script>
Within this function, create a variable called authors
that is set equal to data
:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
})
</script>
For each author in authors
, you will want to create a list item that displays their name. The map()
method is suited for this pattern:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
authors.map(function(author) {
});
})
</script>
Within your map
function, create a variable called li
that will be set equal to createElement
with li
(the HTML element) as the argument. Also, create an h2
for name
and a span
for email
:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
authors.map(function(author) {
let li = document.createElement('li');
let name = document.createElement('h2');
let email = document.createElement('span');
});
})
</script>
The h2
element will contain the name
of the author
. The span
element will contain the email of the author
. The innerHTML
property and string interpolation will allow you to do this:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
authors.map(function(author) {
let li = document.createElement('li');
let name = document.createElement('h2');
let email = document.createElement('span');
name.innerHTML = `${author.name}`;
email.innerHTML = `${author.email}`;
});
})
</script>
Next, connect these DOM elements with appendChild
:
<script>
// ...
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
authors.map(function(author) {
let li = document.createElement('li');
let name = document.createElement('h2');
let email = document.createElement('span');
name.innerHTML = `${author.name}`;
email.innerHTML = `${author.email}`;
li.appendChild(name);
li.appendChild(email);
list.appendChild(li);
});
})
ul.appendChild(list);
</script>
Note that each list item is being appended to the DocumentFragment
list
. Once the map
is complete, the list
is appended to the ul
unordered list element.
With both then()
functions completed, you can now add the catch()
function. This function will log the potential error to the console:
<script>
// ...
fetch(url)
.then((response) => {
// ...
})
.then((data) => {
// ...
})
.catch(function(error) {
console.log(error);
});
// ...
</script>
This is the full code of the request you created:
<h1>Authors</h1>
<ul id="authors"></ul>
<script>
const ul = document.getElementById('authors');
const list = document.createDocumentFragment();
const url = 'https://jsonplaceholder.typicode.com/users';
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
let authors = data;
authors.map(function(author) {
let li = document.createElement('li');
let name = document.createElement('h2');
let email = document.createElement('span');
name.innerHTML = `${author.name}`;
email.innerHTML = `${author.email}`;
li.appendChild(name);
li.appendChild(email);
list.appendChild(li);
});
}).
.catch(function(error) {
console.log(error);
});
ul.appendChild(list);
</script>
You just successfully performed a GET request using the JSONPlaceholder API and the Fetch API. In the next step, you will perform POST requests.
Fetch defaults to GET requests, but you can use all other types of requests, change the headers, and send data. Let’s create a POST request.
First, include a constant variable that holds the link to the JSONPlaceholder API:
const url = 'https://jsonplaceholder.typicode.com/users';
Next, you need to set your object and pass it as the second argument of the fetch function. This will be an object called data
with the key name
and value Sammy
(or your name):
// ...
let data = {
name: 'Sammy'
}
Since this is a POST request, you will need to state that explicitly. Create an object called fetchData
:
// ...
let fetchData = {
}
This object needs to include three keys: method
, body
, and headers
:
// ...
let fetchData = {
method: 'POST',
body: JSON.stringify(data),
headers: new Headers({
'Content-Type': 'application/json; charset=UTF-8'
})
}
The method
key will have the value 'POST'
. body
will be set equal to the JSON.stringify()
format of the data
object that was just created. headers
will have the value of 'Content-Type': 'application/json; charset=UTF-8'
.
The Headers
interface is a property of the Fetch API, which allows you to perform actions on HTTP request and response headers. This article called How To Define Routes and HTTP Request Methods in Express can provide you with more information.
With this code in place, the POST request can be made using the Fetch API. You will include url
and fetchData
as arguments for your fetch
POST request:
// ...
fetch(url, fetchData)
The then()
function will include code that handles the response received from the JSONPlaceholder API:
// ...
fetch(url, fetchData)
.then(function() {
// Handle response you get from the API
});
This is the full code of the request you created:
const url = 'https://jsonplaceholder.typicode.com/users';
let data = {
name: 'Sammy'
}
let fetchData = {
method: 'POST',
body: JSON.stringify(data),
headers: new Headers({
'Content-Type': 'application/json; charset=UTF-8'
})
}
fetch(url, fetchData)
.then(function() {
// Handle response you get from the API
});
Alternatively, you can pass fetch()
a Request
object.
const url = 'https://jsonplaceholder.typicode.com/users';
let data = {
name: 'Sammy'
}
let request = new Request(url, {
method: 'POST',
body: JSON.stringify(data),
headers: new Headers({
'Content-Type': 'application/json; charset=UTF-8'
})
});
fetch(request)
.then(function() {
// Handle response you get from the API
});
With this approach, request
can be used as the sole argument for fetch()
, replacing url
and fetchData
.
Now you know two methods for creating and executing POST requests with the Fetch API.
While the Fetch API is not yet supported by all the browsers, it is a great alternative to XMLHttpRequest
.
If you would like to learn how to call Web APIs using React, check out this article on this very topic.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
i created an account to say this. although the article is helpful the syntax highlighting is atrocious my eyes are bleeding please change the colors please
Hey, Sara, thanks for the article. There are some minor typos in Step 2 full code so it doesn’t work. I´ve checked and change a little bit and now it´s ok:
<h1>Authors</h1>
<script> const ul = document.getElementById(‘authors’); const list = document.createDocumentFragment(); const url = ‘https://jsonplaceholder.typicode.com/users/’;
fetch(url) .then((response) => { return response.json(); }) .then((json) => { json.map(function(author) { let li = document.createElement(‘li’); let name = document.createElement(‘h2’); let email = document.createElement(‘span’);
</script>
I have may be a basic question, with the url, when I work on visual studio url it’s like https://localhost:3030/api/something but when I publish it’s like https://myserver:3030/api/something how can I handle this to avoid change url in all my functions because is hardcode basically