close icon
daily.dev platform

Discover more from daily.dev

Personalized news feed, dev communities and search, much better than what’s out there. Maybe ;)

Start reading - Free forever
Continue reading >

A Guide To Writing Clean API Calls Using Axios

A Guide To Writing Clean API Calls Using Axios
Author
Agustinus Theodorus
Related tags on daily.dev
toc
Table of contents
arrow-down

🎯

Introduction

Making frontend applications is not as simple as it used to be. Frontend frameworks like React, and Vue rely heavily on APIs. This adds complexity to our app because we need to manage how we call these APIs. One solution is, we can simplify it by writing clean API calls.

But wait, what are “Clean API calls”? Well for me personally I see it as a term that means proper structuring of API calls, making it easy to read and maintain. First, I do this by utilizing the single responsibility principle. Each function must have a single responsibility, by having this principle in mind we need to separate logic for each endpoint. 

The other thing I try to manage is the DRY principle or “Don’t Repeat Yourself”. This is very important, arguably more so in the case of frontend API providers because it gives the sense of tidiness in the code thus improving readability. This is the case of why I try to use Axios because it gives features such as interceptors, defaults, etc. It reduces the amount of boilerplate code you need to write for each API endpoint.

Pros and Cons of Using Axios

There are many ways to achieve this, you can either use JavaScript’s fetch API or you can use a third-party library called Axios. By the title of this article, you can guess that I prefer Axios. Why Axios? Let’s weigh in on the pros and cons:

Pros

1. Simplicity

What I like most about Axios is that it is very simple to use. The programming API is so easy to use that I have gotten so used to it. Well, this might be too personal of a preference but you can try it yourself. I have used jQuery’s AJAX and ES6 Fetch API and I would rank Axios above all of them. Although not by too large of a margin since all three of them are nice to work with.

2. Backwards compatibility

Honesty, you wouldn’t think about this feature until you need it. I mean, most people have modern browsers, but if some of your customers aren’t most people they might not be able to use your app if it wasn’t backward compatible. ES6 Fetch API is relatively new and old browsers aren’t capable of using it. Otherwise, libraries like Axios and jQuery’s AJAX are built on top of Javascript’s XMLHttpRequest. For those of you who are wondering, XMLHttpRequest is an old version of Javascripts in-built HTTP calling mechanism.

3. Mature library with lots of features

You can do a lot with Axios, a whole lot. For example, as of the writing of this article, JavaScript’s Fetch API does not have request/response interceptors built-in. You have to use other third-parties to do so. Compared to fetch, writing clean APIs using Axios is very simple. Axios already have so many built-in conveniences. To name a few, you can set default headers, and set default base URLs using Axios.

Cons

1. Too sophisticated for small apps

I have used Axios for a long time to understand that this library can be overkill for small apps. I mean if you only need to use its GET, and POST APIs you probably are better off with ES6 Fetch API anyway. Fetch is native to Javascript, Axios is not. This brings us to the next point.

2. Axios bloats your bundle size

This second point corresponds to the first one perfectly. One of the main reasons I avoid the use of Axios for small apps is the fact that it bloats your production build size. Sure, you might not notice a size spike for large apps like e-commerce and such. But you will notice a huge increase if you are making a simple portfolio site. The lesson to be learned? Use the right tools for the right job.

3. It’s a third party

Look, let me just start by saying, this third point is really subjective and some people might have opposite views. Axios is a third party. Yes, you heard it right. It is not native to Javascript, unlike Fetch. You depend on the community to maintain your precious app. But then again, most apps these days do use open-source products, so would it be a problem? Not really. Again this is a preference. I am not advising you to reinvent the wheel. Just understand that you don’t own the wheel.

Installing Axios

Axios is available in multiple JavaScript repositories, you can access it using yarn and NPM. If you are using regular HTML you can import it from CDNs like jsDelivr, Unpkg, or Cloudflare. 

Assuming you are using NPM, we need to install Axios using this command:


npm install -S axios

If there are no errors in the installation then you can continue to the next step. You can check alternative installation methods.

Making separate Axios clients

What are Axios clients? Clients are how we set default parameters for each API call. We set our default values in the Axios clients, then we export the client using JavaScript’s export default. Afterward, we can just reference the client from the rest of our app.

First, make a new file preferably named apiClient.js and import Axios:


import axios from 'axios';

Then we make a client using axios.create.


const axiosClient = axios.create({
  baseURL: `https://api.example.com`,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  }
});

As you can see, we initiated the base URLs and default headers for all our HTTP calls.

Using interceptors for clean redirects

When calling interacting APIs, especially when there is authentication involved. You will need to define conditions when your call is unauthorized and make your application react appropriately. Interceptors are perfect for this use case.

Let’s say that we will need our application to redirect us to our home page when our cookies expire and when our cookie expires the API will return a 401 status code. This is how you would go about it:


axiosClient.interceptors.response.use(
  function (response) {
    return response;
  }, 
  function (error) {
    let res = error.response;
    if (res.status == 401) {
      window.location.href = “https://example.com/login”;
    }
    console.error(“Looks like there was a problem. Status Code: “ + res.status);
    return Promise.reject(error);
  }
);

Simple right? After you’ve defined your client and attached an interceptor you just need to export your client to be used on other pages.

Exporting Axios Client

After configuring your Axios client, you would need to export it to make it available for the entire project. You can do this by using the export default feature:


export default {
  axiosClient
);

Now we have made our Axios client available for the entire project. Next, we will be making API handlers for each endpoint.

Folder structure

Before we continue, I thought it would be handy to show you how to arrange your subfolders. Instead of writing a long comprehensive explanation, I think it would be better for me to give you an image of what I am talking about:

Image of the folder structure

Assuming we will have an admin, user, and product endpoints. We will home the apiClient.js file inside the root of the network folder. Although, regarding the naming of the folder or even the structure is my personal preference.

The endpoints will be put inside a lib folder and separated by concerns in each file. For example, for authentication purposes, user endpoints would be put inside the user file. Product-related endpoints would be put inside the product file.

Writing an API Handler

Now we will be writing the API handler. Each endpoint will have its asynchronous function with custom parameters. All endpoints will use the client we defined earlier. To make a simple example, I will write two API handlers to get new products and to add new products.


import { axiosClient } from "../apiClient";

export function getProduct(){
    return axiosClient.get('/product');
}

export function addProduct(data){
    return axiosClient.post('/product', JSON.stringify(data));
}

This pretty much sums up how I intend to write an API handler, and as you can see each API call is clean and it all applies the single responsibilities principle. You can now reference these handlers on your main page.

Using the handlers in your web app

Assuming that you are using an NPM project for all of this, you can easily reference your JavaScript API handlers using the import method. In this case, I will be using the getProduct endpoint:


import { getProduct } from "../network/lib/product";

getProduct()
  .then(function(response){
    // Process response and
    // Do something with the UI;
  });

There you have it, a clean no-fuss API handler. You successfully made your app much more readable and easier to maintain.

Final Words

Having an app that works is great, you get all the functionalities right and you are practically finished. However, people tend to forget that they need to maintain that app. So, sooner or later you will have to read that code all over again. And wouldn’t it be better if it was all readable and easier to understand? With a great separation of concerns. I think we would all want that, and I would even say we will be very proud if we can read the code we wrote 1 year back.

Being fast does not guarantee success but being consistent and responsible does. Write better code, and help your team grow! Thanks for reading, have a nice day.

Why not level up your reading with

Stay up-to-date with the latest developer news every time you open a new tab.

Read more