Caching http requests in AngularJS

Posted on 30 September 2015

In AngularJS, especially when you’re using a 'modern' Web Component like approach, you often have directives request the same information from your services multiple times. Since we’d rather not do round-trips we don’t need to to save on server resources caching is our go-to solution. In this post I will show two different approaches to caching resources: the built-in angular way using $resource and a home-grown solution.

Resource

Our first example uses angular-resource. It’s the most straightforward way of accessing REST resources and enabling caching is simply a matter of setting the cache to true on the get method like so:

app.service('weatherService', ['$http', '$resource', function($http, $resource) {
    var Weather = $resource(
        'http://api.openweathermap.org/data/2.5/weather?q=:city',
        {},
        {'get': { method:'GET', cache: true}});

    return {
        getWeatherViaResource: function(city) {
            return Weather.get({ city: city }).$promise;
        }
    };
}]);

Instead of passing in a boolean you can also provide your own $cacheFactory cache. This allows you more control over the cache options (such as max size) and allows you to invalidate entries when required.

Manual approach

Then there is also the manual approach. A $http.get returns a reusable promise that can easily be stored in an object. A manual implementation gives full control over cache size and allows you to use whatever eviction policy you prefer, but the code is less concise than simply using $resource and $cacheFactory:

app.service('weatherService', ['$http', '$resource', function($http, $resource) {
    var weather = {};

    return {
        getWeatherViaHttp: function(city) {
            if(!weather[city]) {
                weather[city] = $http
                    .get('http://api.openweathermap.org/data/2.5/weather?q=' + city)
                    .then(function(response) {
                        return response.data;
                    }
                );
            }
            return weather[city];
        }
    };
}]);

As you can see, having access to the cache object allows us to choose whatever method we want to use the cache. The downside is that we have to write quite a bit more code so it might become tempting to reinvent the wheel to create our own managed cache. If the objective is to simply save on $http round-trips I would strongly suggest just using the $resource approach.

Example

A 'full' AngularJS sample application can be found in this repo. Assuming you have nodeand npm you can run the example with the following steps:

  • Fork the repo

  • Clone your example repo to a directory of your choosing

  • cd into the directory

  • run "npm install" to install the dependencies

  • run "npm start" to start the example application

  • navigate to http://localhost:3000/ to view the application

If you open up the network tab in your developer console and hit F5 you should see that although there are 12 weather displays the system only does 4 http requests (each method does a request for both Utrecht and Amsterdam).

This concludes this blog post. If you have any questions or suggestions feel free to poke me on github, twitter or google+!