At Agira, Technology Simplified, Innovation Delivered, and Empowering Business is what we are passionate about. We always strive to build solutions that boost your productivity.

How to Cache HTTP Requests In Angular

  • By Vignesh M
  • April 2, 2020
  • 2252 Views

Angular is a great choice for any large scale enterprise projects because it is opinionated and brings the whole team together on many things. It is like having a headstart for your development team. Though angular has so many things defined, still there are some things that you have to figure out on your own.
One such thing is caching HTTP requests, as per the famous quote by Phil Karlton,
“There are only two hard things in Computer Science: cache invalidation and naming things.”, Caching things is very easy but clearing the cache is difficult. We are going to see an approach that puts you in control of both caching an HTTP request and invalidating the cache.
First, let’s define a property in your service which caches the result of the HTTP request

data-sheets-value="{"1":2,"2":"private userList$: Observable<any>;"}" data-sheets-userformat="{"2":513,"3":{"1":0},"12":0}">private userList$: Observable<any>;

I’m using any type here for the sake of example, in real-world applications you should not be using any type like this. Now let us write the service method that makes the HTTP request.

public getUsers$(): Observable<any> {
if (!this.userList$) {
this.userList$ = this.httpClient.get('/users');
}
return this.userList$;
}

The above code is pretty self-explanatory, we are checking if the observable is already defined and if it isn’t we are making the HTTP call and then store the reference in the member observable we created. Next time this function gets called, the existing reference to the observable will be returned without actually making a fresh HTTP call.

ALSO READ: MongoDB In Golang With Examples – A Beginner’s Guide

In theory, The above code should work but if you try that code in a real project you can see that you’re still making multiple HTTP calls. Why? We already have them cached. To understand why this happens, we should understand how observables work and the difference between a hot observable and a cold observable. 
A hot observable is something that runs immediately once it is created, cold observables, on the other hand, won’t run until you make the first subscription. Http calls using the angular HttpClient are using cold observables. Let’s take a look at a simple example here.

const obs = Observable.create(observer => observer.next(Math.random()));
obs.subscribe(res => console.log(res));
obs.subscribe(res => console.log(res));

If you run the above code you can see that for each subscription a new value is produced meaning that the observable is emitting new values on each subscription because it is cold. But to cache values, For caching we should not let the observable produce values for each subscription so we should turn it into a cold observable and then cache the value it produced the first time.
It is simple to do that using different rxjs operators, I prefer to use ShareReplay to do that. 

const obs = Observable.create(observer => observer.next(Math.random())).pipe(shareReplay(1));
obs.subscribe(res => console.log(res));
obs.subscribe(res => console.log(res));

If you run the above code, you can see that only the same value is written on the console for both calls, It is because shareReplay run the creation function even before the first subscription, then share the results of the call for every new subscription.
You might have seen some examples that use publishReplay with refCount() which unsubscribe from the source observable, you can do the same in shareReplay as well in a little different way. But it depends on whether you want to unsubscribe from the source when no subscribers are there. If you want to do it, here is how it can be done in shareReplay().

observer.next(Math.random()))
.pipe(shareReplay({refCount: true, bufferSize: 1}));

I hope that we have covered enough about the hot/cold observables and what shareReplay, refCount is doing. Here is our final method for caching after including sharedReplay.

public getUsers$(): Observable<any> {
  if (!this.userList$) {
      this.userList$ = this.httpClient.get('/users')
      .pipe(shareReplay(1));
}
  return this.userList$;
}

Now you can use the getUsers$ method like any other normal service method and subscribe to its observable, let’s see how we can write a method that invalidates the cache and let us refresh the cached values.

Private clearUsers(): void {
this.userList$ = null;
}

The above function will set the cached observable to null which will force the getUser$ method to make an HTTP call when it is called again. 

ALSO READ: How To Develop A Healthcare Mobile Application For Hospitals

This caching will not keep the data across application reloads, but it is not hard to implement by writing the response to a persistent client-side storage mechanism, such as localStorage or IndexedDB and then putting it back into the stream on application bootstrap. This deals with caching at individual service methods level which should be enough for most applications but there are other approaches to caching such as using an interceptor to handle the request and cache the response which is done at the whole application level. That topic warrants a blog post on its own. I hope you found this blog useful, feel free to share your thoughts in the comments.
Do you find it interesting? you might also like these articles. Top 10 Best Tech Companies For Employees To Work In The USA In 2020 and Top 10 IT Staffing and Recruiting Agencies in the USA.
If you have a business idea in your mind and in search of a reliable web development company, you are in the right place. Hire the best web developers in the industry from Agira technologies.

Looking for a Tech partner to dominate the digital world?

Vignesh M

An energetic Fullstack developer/Tech Lead and has a strong desire in Programming. With 6.5 years of experience in Angular, Javascript, Laravel PHP, Ionic, and Flutter, he always strives to come up with Smart Solutions to accomplish complex tasks.He is also interested in Video games, Motorcycles, Books, Movies, History.