Contact

Ensuring an easier migration path with framework-agnostic libraries using Axios

Jaroslaw Zolnowski
January 11, 2023

Introduction

How often do you use data in your applications? I do this in every application I implement.

We typically fetch data using an HTTP client in a service. Sometimes, the HTTP client is even used directly in a component, which is not very good practice. But this article is not about good and bad practices, so let’s move on.

So inside the Service, we can inject another Service, for example, $http (AngularJS), or HttpClient (Angular). The built-in HTTP Angular services are outstanding.

Why are we using them?

When AngularJS was written, the browsers didn't have a fetch() API. Well, now times have changed, and they do!

So why don’t we use fetch() instead of the HTTP client? You might think:

Well, it’s just easier to use the build-in HTTP client

or simply:

Why should I use something else if I get an HTTP client with the framework I’m using?

Think about React, Vue.js, other web frameworks or just plain JavaScript. What are they using? Well, they use the fetch() API. And if they need something more complex and involved, they can use things like Axios - a promise-based HTTP client for Node.js and the browser.

Axios Logo

Axios in action

Let’s look at an AngularJS and Angular-based application that does not use the built-in HTTP client. Here’s what it might look like in AngularJS:

import axios, {AxiosResponse} from 'axios';
import {User} from '../users.module';

export class UsersService {
  loadAllUsers(): Promise<AxiosResponse<User[]>> {
    return axios.get('assets/mocks/users.json');
  }
}

and Angular:

import {Injectable} from '@angular/core';
import axios, {AxiosResponse} from 'axios';
import {User} from '../users.module';

@Injectable({
  providedIn: 'root'
})
export class UsersService {
  loadAllUsers(): Promise<AxiosResponse<User[]>> {
    return axios.get('assets/mocks/users.json');
  }
}

So, as we can see, we define a service called UsersService in both cases. And you’ll notice we're pulling in Axios. We can also see a method named loadAllUsers(). That method invokes Axios APIs, which return a Promise which will eventually resolve with the returned data.

The code examples above are straightforward and very similar. But notice what you do not see as well. It’s not just the HTTP service switched out for Axios in this case.

Where are the Observables in the Angular-based code example?

Now RxJS is extremely powerful and valuable. But do you ever feel weighed down when you’re getting into a new technology? Maybe you feel like:

I don’t need this yet

I shouldn't need to learn all of these concepts to understand a basic example.

Well, with this, you don’t have to. With fetch() and Axios, you can jump right into using Promises. But there is an even more significant advantage that we may overlook at first glance.

Migration from AngularJS to Angular

As some of you know, migrating an AngularJS-based application to Angular is a real challenge. Interfaces and APIs are so different that it's safe to say that they are two completely different frameworks. The way the HTTP client is used in the two mentioned versions is also completely different.

Here is an example of how we use the built-in $http service in AngularJS:

import {IHttpResponse, IHttpService} from 'angular';
import {User} from '../users.module';

export class UsersService {
  constructor(private $http: IHttpService) {
  }

  loadAllUsers(): Promise<IHttpResponse<User[]>> {
    return this.$http.get('assets/mocks/users.json');
  }
}

And here is an example of using the built-in HttpClient service for Angular:

@NgModule({
  imports: [HttpClientModule],
  ...
})
export class UsersModule {
}
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {User} from '../users.module';

@Injectable({
  providedIn: 'root'
})
export class UsersService {

  constructor(private http: HttpClient) {
  }

  loadAllUsers(): Observable<User[]> {
    return this.http.get<User[]>('assets/mocks/users.json');
  }
}

Maybe we should consider using a library that is independent of the framework used and guarantees a consistent API, whether in AngularJS, Angular or even React. Is Axios worth using? We would save ourselves the problem and time of rewriting all Services to an entirely new API.

So, does the built-in HTTP client have any use?

There are some reasons why AngularJS/Angular have their HTTP clients.

In both frameworks, the respective HTTP clients tie into the change detection system, automatically triggering a change detection as soon as a response is received.

If we use fetch() or Axios, we might need to handle that ourselves. This is not necessarily prohibitively complicated, but it’s worth remembering.

Another difference in AngularJS that could break your application if not addressed is that the built-in HTTP client returns $q promises, the AngularJS’s built-in promise type rather than regular Promise instances. So it is worth paying attention to what type is returned from the services and considering this argument when making a decision about the HTTP client.

Another difference worth mentioning when using fetch() is that it does not support some features offered by built-in clients, such as request/response interception, transformations, etc.

One last difference between fetch() and Axios is that they might be a little less easy to handle in tests compared to the built-in HTTP clients, which offer utilities that make testing easier.

With the above in mind, we should decide on the HTTP client based on our goals and objectives.

Summary

I am not trying to convince anyone that Axios is better than HttpClient. But I hope I have succeeded in getting you to reflect on the future of your application. Perhaps years from now, Angular will be another completely different framework implementing a new API. Regardless, using a framework-agnostic library like Axios will ensure that your code that fetches data will look and function similarly!

Sample application code based on AngularJS and Axios is available in this GitHub repository.

Looking for more support for your Angular projects?

Our team at DevIntent is highly experienced in web development, including framework migration and updates. Check out our offerings or reach out.



Image by upklyak on Freepik
Jaroslaw Zolnowski
January 11, 2023