AngularJS’s super secret $http caching abilities
How to customize $http’s built-in caching functionality
Actually, it’s not secret — it’s documented right here. Although, I find that not a lot of people know about that feature. But there’s more to it than is documented there, so don’t worry, keep reading 😀.
Basically, you can do this:
…and get some caching for free. Easy!
Passing the cache: true property tells angularJS to cache the response in a cache created by $cacheFactory. (See the angularJS source for that here). That cache is an LRU (least recently used) cache with no limit to it’s capacity.
The $http cache will cache the promise created before the underlying XMLHttpRequest is sent, so if you make the same request again before the request has resolved, it returns the cached promise. Consequently, an identical, duplicate request is not made. This is pretty handy for a number of situations and provides an easy perf win for the front-end and the back-end.
But a cache that grows infinitely with every request to a unique URL? That doesn’t sound so great, so luckily we can configure it a bit by passing our own cache to that property, like so:
That cache is now no longer global to all $http requests and will only hold up to 10 items in it at a time.
Side note: how do LRU caches work?
An LRU cache deletes the least recently used item after it has met it’s capacity. It’s usually implemented with a doubly linked list where the most recently used item, whether it’s new or already in the cache, is moved to the front. Items not used recently, gradually move further back in the list. When it has met it’s capacity, it removes the tail item from the list. That’s how it works in angularJS and in a popular node.js implementation, lru-cache.
But what if I wanted to cache some data for awhile, but not indefinitely, and expire it after some time?
You can provide your own cache implementation to $http and pass it to the cache property. Let’s see what an implementation of a cache that expires entries after 5 seconds would look like:
So basically I’m implementing the same interface that caches created via $cacheFactory do, and providing that to $http instead. AngularJS calls all the methods on it just as you’d expect because the interface is the same. Cool! AngularJS should have had that in their docs for all these years.
There are definitely other ways to achieve this kind of caching in angularJS, such as by wrapping the $http request. I like this approach better because it’s easier to reuse and drop-in to existing implementations.
There you have it! AngularJS’s $http cache property can work with any object that fulfills the $cacheFactory interface.