Making API calls in Vue with Axios
To fetch data from an API, JavaScript comes with libraries like Fetch and Axios. These libraries have an easy syntax and can be easily integrated with popular front-end frameworks like React, Angular, and Vue. In this article, we will focus on making API calls from a Vue application using Axios, a Promise-based HTTP client for the browser and Node.
To get the most out of this article, you’ll need a basic understanding of Vue (check out the official Vue docs) and how the client-server model works.
Example Project
I have built a basic Vue-CLI app to test the requests we will make during this tutorial. You can read more about creating one here. The complete code for this project can be found here.
On clicking the buttons, respective functions are invoked to execute the API calls.
I have created everything in the App.vue component to keep it simple. The bootstrap CDN has been added to the index.html
file. We will be making all the API calls in the script block. You can read about the template
, script
and styles
block here
Here’s the template
block:
<template>
<div class="container my-5">
<div class="text-center">
<h1 class="display-4 text-center mb-3">Making API calls in Vue</h1>
<div class="center">
<div class="row">
<div class="col-lg-6">
<button v-on:click="onGet" class="btn btn-primary my-3">GET</button>
<button v-on:click="onSimultaneous" class="btn btn-info">Concurrent requests</button>
<button class="btn btn-danger"> Error Handling </button>
</div>
<!-- POST -->
<div class="col-lg-6">
<h2>Post</h2>
<form @submit.prevent="onPost">
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" v-model="title" required/>
</div>
<div class="form-group">
<label></label>
<textarea class="form-control" v-model="body" required></textarea>
</div>
<div class="mt-3">
<button type="submit" class="btn btn-primary">
Create Post
</button>
<button type="submit" class="btn btn-secondary">
Add with Custom Headers
</button>
</div>
</form>
</div>
</div>
<hr />
</div>
</div>
<hr />
<div>
{{ res }}
</div>
</div>
</template>
Making GET requests
Before making HTTP requests, let’s ensure you have installed Axios in your project. You can install Axios using the node package manager or Yarn.
npm install axios
We will use Axios to make a GET
request inside the onGet()
method. This function gets invoked once the user clicks the GET
button. I have used the JSON placeholder API, which generates JSON data of some random dummy To-do list entries.
The output from the API is stored in the res
, which has been declared in the data method. This will be further called in the template
block to view the response in the browser.
<script>
import axios from "axios";
export default {
data() {
return {
res: [],
};
},
name: "App",
methods: {
// The get method called by the function
onGet() {
axios
.get("https://jsonplaceholder.typicode.com/todos")
.then((response) => {
console.log(response);
// using stringify to beautify the output
this.res = JSON.stringify(response.data);
})
.catch((errors) => {
console.log(errors); // Errors
});
},
},
};
</script>
The then()
method has been used to handle the response. If there’s some error, this promise is rejected, and the next promise is called.
A response object consists of the following information
- data - response provided by the server
- status - HTTP status code from the server
- statusText - HTTP status message from the server
- Headers - meta-data associated with the API request. Read more
- config - config that was provided to Axios during the request
- request - the request that was sent to generate this response.
We have used response. data
and the output for the above code would look like this:
To limit the number of objects in the output, we can send a param
with a limit set to 5. We can send different parameters according to our requirements. Read more about it here
axios
.get("https://jsonplaceholder.typicode.com/todos", {
params: {
_limit: 5,
},
})
.then();
Alternatively, we can change the URL to :
https://jsonplaceholder.typicode.com/todos?_limit=5
Adding the URL again and again in every request can be tiring. Hence we can use a property to set the base URL in the main.js
, the entry point for the code.
Axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com/';
This sets the baseURL, and hence the modified onGet
method looks like this:
onGet() {
axios
.get("todos/?limit=5")
.then((response) => {
console.log(response);
this.res = JSON.stringify(response.data);
})
.catch((errors) => {
console.log(errors);
});
}
We get five to-do list entries on the web page.
Concurrent Requests
axios.all
is a helper method built in Axios to deal with concurrent requests. Instead of making multiple HTTP requests individually, the axios.all
method allows us to make multiple HTTP requests to our endpoints.
On clicking the Concurrent requests button, data from 2 different APIS, i.e., To-do and Posts, should be fetched and displayed on the browser.
axios.all
takes an array of requests, in this case: requestOne
and requestTwo
.
onSimultaneous() {
// Defining the URLs we want to access
// POSTS API
let one = "https://jsonplaceholder.typicode.com/posts?_limit=1";
// TODO LIST API
let two = "https://jsonplaceholder.typicode.com/todos?_limit=1";
// Method we want to perform on those URLS
const requestOne = axios.get(one);
const requestTwo = axios.get(two);
// Resolving the two requests
axios
.all([requestOne, requestTwo])
.then(
axios.spread((...responses) => {
// Response from posts
const responseOne = responses[0];
// Response from Todos
const responseTwo = responses[1];
this.res[0] = responseOne.data;
this.res[1] = responseTwo.data;
console.log(this.res);
})
)
.catch((errors) => {
// react on errors.
console.error(errors);
});
}
We can check the console to see that responses to both requests have been logged.
Doing POST Requests
I have created a database in Firebase to see the reflected changes made after the POST request. Read more about how to create one here
For making a POST request in Axios, two parameters are required:
- the URL of the service endpoint
- an object that contains the properties you wish to send to the server.
We take the title and body from the user via a form input. On submitting the form, the onPost
method is invoked to make a POST request and send the data to the database.
We have also updated the baseURL in the main.js
file to the firebase URL
onPost() {
axios
.post('posts.json', {
title: this.title,
body: this.body,
})
.then(response => {
console.log(response)
this.res = "Status " + response.status + " Post created";
})
.catch(err => console.error(err));
},
The data is added to the Firebase database and Voila! We just created our first post!
Similarly, we can do the PUT/PATCH, DELETE request using the Axios properties. You can read more about it here and here
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.
Sending Custom Headers
To send an access token, we can use different headers; the Authorization
header is one of them. For detailed information, checkout
We will discuss two methods to send headers with the request in Axios.
1. Passing Object argument
We can create an object and pass the necessary headers to it. This object can be sent with the request, and the POST request code gets modified to:
axios.post(
"posts.json",
{
title: this.title,
body: this.body,
},
{
headers: {
"Content-Type": "application/json",
Authorization: "KrvLC6sUgU",
},
}
);
On checking the Network Tab, we can see the headers we passed in the request.
It can be tedious to set the headers again and again, so we can set the default header in the main.js
file. This code sets authorization headers for all the post
requests:
Axios.defaults.headers.post['Authorization'] = `Bearer ${localStorage.getItem('access_token')}`;
2. Axios Instance
We can also set request headers for API calls by creating a specific instance of Axios. We can reuse this configuration each time we make a request using this particular instance.
Let’s create a services
folder with a file axiosInstance.js
in it and write the following code :
const { default: Axios } = require("axios");
const axiosinstance = Axios.create({
baseURL: "https://jsonplaceholder.typicode.com",
});
axiosinstance.defaults.headers.common["Authorization"] = "Dummy Token";
export default axiosinstance;
We can use this axiosInstance directly in any of the requests by importing.
import axiosinstance from '../services/axiosinstance';
and using it in the request
axiosinstance.get("todos").then((response) => {
console.log(response);
});
The respective headers are sent; thus, this method can be used to send specific headers to some requests.
You can also read about Axios interceptors, which are used for handling Authorization.
While making these requests, there are chances that the app may crash due to many reasons from the server side like data unavailability, wrong request format sent to the server, etc. It is imperative to monitor these errors as it helps in debugging the code.
Error Handling
To avoid the web application from crashing, we can handle the errors by displaying messages/alerts to make the user aware. Instead of simply console logging the error, we can capture the errors and send a custom message to improve the user experience.
Let’s create a function onError
to understand Error Handling. We are using the wrong URL to get an error while fetching the data.
If our error object consists of a response field, we can use err. response
to check the root cause of the error. Similarly, if our error object has a request field, we can use the err.request
.
axios
.post(url, data)
.then((res) => {
//Everything works fine
})
.catch((err) => {
if (err.response) {
// client received an error response (5xx, 4xx)
} else if (err.request) {
// client never received a response, or request never left
} else {
// anything else
}
});
On clicking the Error Handling
button, the onError
function is invoked, and an alert is sent to display the errors.
onError() {
axiosInstance
.get("todoss", {})
.then((response) => console.log(response))
.catch((err) => {
if (err.response) {
// Server responded with a status other than 200 range
console.log(err.response.data);
if (err.response.status === 404) {
alert("Error: Page Not Found");
}
} else if (err.request) {
// Request was made but no response
console.error(err.request);
} else {
console.error(err.message);
}
});
}
Using error handling is one of the good practices while writing APIS. You can read more about handling errors in Axios here.
We pretty much covered all the basics of making API calls in a Vue application using Axios in this article. You can deep dive into this by referring to the official docs and try your hands on it!
A TIP FROM THE EDITOR: For more on using Axios, be sure not to miss our How to Make HTTP Requests with Axios and Fetch vs. Axios: Which Is the Best Library for Making HTTP Requests? articles.