Intro

Angular.js rocks and you’re flying high making AJAX requests left and right. Inject $http, shoot off a request and boom—the promise-based service hits your error or success callback.

$http.get('/foo/bar/' + itemId)
  .success(function (data) {
    data; // { foo: 'bar' }
  })
  .error(function (data, status, headers, config) {
    // uh oh
  });

Okay, so you’ve got your data from your backend—now what? This particular bit of data doesn’t change very often, and you’re wondering why your client repeatedly makes the same request for the same data—what a waste! Save your users some time and bandwidth and tell that request to use caching!

$http.get('/foo/bar/' + itemId, { cache: true })
  .success(function (data) {
    data; // { foo: 'bar' }
  })
  .error(function (data, status, headers, config) {
    // uh oh
  });

Sweet! Now, the first time $http sends a GET request to /foo/bar/123, for example, the response will be stored in a cache named “$http”. This cache is created by Angular’s $cacheFactory as the default cache for the $http service when Angular boots up. { cache: true } tells the $http service to cache the response to that particular request in $http’s default cache. You don’t have to do anything else. Any subsequent requests to /foo/bar/123 will simply use the cached reponse. Neat!

If you want you can actually reference $http’s default cache and retrieve items, remove items, clear the cache, etc. Just inject $cacheFactory into whatever you’re working with, and reference $http’s default cache via:

var $httpDefaultCache = $cacheFactory.get('$http');

You can retrieve the cached response to the above GET requested by using the absolute url of the request.

var cachedData = $httpDefaultCache.get('http://myserver.com/foo/bar/123'); // { foo: 'bar' }

You can clear that item from the cache:

$httpDefaultCache.remove('http://myserver.com/foo/bar/123');

Or clear the whole cache:

$httpDefaultCache.removeAll();

See $cacheFactory for a complete reference.

LRU Cache

What if you don’t want $http’s default cache to store every response? Simple: turn it into an LRU Cache (Least Recently Used).

// Create a new cache with a capacity of 10
var lruCache = $cacheFactory('lruCache', { capacity: 10 });

// Use the new cache for this request
$http.get('/foo/bar/' + itemId, { cache: lruCache })
  .success(function (data) {
    data; // { foo: 'bar' }
  })
  .error(function (data, status, headers, config) {
    // uh oh
  });

The reponse to each request to /foo/bar/:itemId will be cached, but this time the cache only has a capacity of 10. When the eleventh unique request is made the least recently accessed item will be removed from the caching, keeping the total number of cached items at 10. This cache maintains a list of its items in order of how recently they have been accessed so it knows which one to remove when storing a new item would exceed the capacity.

Setting a default cache

As shown in the LRU example you can tell an $http request to use a cache other than $http’s default cache, but what if you wants to change $http’s default cache? It’s easy:

$http.defaults.cache = $cacheFactory('myNewDefaultCache', { capacity: 100 });

$http will now use myNewDefaultCache as its default cache.

Advanced Caching

What if you want to cache data to improve user experience, but the data is liable to change once a day, or every few hours, etc. You would want to make sure your cached data gets cleared at least once a day, every ten minutes, etc. Unfortunately Angular’s $cacheFactory does not provide any such capabilities.

You could hack something together using setInterval() or setTimeout(), but you don’t want to do that. To solve this problem I created angular-cache, a drop-in Angular module that gives you access to $angularCacheFactory, which creates caches with more capabilities. With angular-cache your caches can periodically clear themselves with cacheFlushInterval. When adding to a cache you can specify a maxAge, which is the maximum amount of time that particular item will be in the cache before it is automatically removed. Or you can specify a maxAge for the whole cache which will be applied to every item added to the cache.

I’ll refer you to the angular-cache documentation for further reference.

Happy caching!