The docs for angular-cache 2.x.x are being deprecated. Please consider upgrading to 3.x.x
Fork me on GitHub

Guide

Learn how to use angular-cache and read about common usage patterns.

Create a cache

First, inject $angularCacheFactory then create as many caches as you so desire. Let's go:

app.service('myService', function ($angularCacheFactory) {

    // Create a new cache called "profileCache"
    var profileCache = $angularCacheFactory('profileCache');
});

Let's add some items to the cache:

profileCache.put('/profiles/34', {
    name: 'John',
    skills: ['programming', 'piano']
});

profileCache.put('/profiles/22', {
    name: 'Sally',
    skills: ['marketing', 'climbing', 'painting']
});

Right now, these items will stay in the cache indefinitely. What if, for the sake of the example, I know that users change their skills in their profile once a week. The profile information is subject to change, but we don't want to make tons of requests for profiles that probably haven't changed.

Let's have items which are added to profileCache expire after an hour:

profileCache.setOptions({
    maxAge: 3600000
});

Perfect. Say we also want the items removed from the cache when they expire:

profileCache.setOptions({
    deleteOnExpire: 'aggressive'
});

Let's say that when the items do expire, we want to refresh them with new values:

profileCache.setOptions({
    onExpire: function (key, value) {
        $http.get(key).success(function (data) {
            profileCache.put(key, data);
        });
    }
});

Sweet! Now we'd probably have configured our cache correctly when we created it:

var profileCache = $angularCacheFactory('profileCache', {
    maxAge: 3600000,
    deleteOnExpire: 'aggressive',
    onExpire: function (key, value) {
        $http.get(key).success(function (data) {
            profileCache.put(key, data);
        });
    }
});

Or say we want all of our caches to use that configuration as their default:

angular.module('app', ['jmdobry.angular-cache'])
    .config(function ($angularCacheFactoryProvider) {

        $angularCacheFactoryProvider.setCacheDefaults({
            maxAge: 3600000,
                deleteOnExpire: 'aggressive',
                onExpire: function (key, value) {
                    $http.get(key).success(function (data) {
                        profileCache.put(key, data);
                    });
                }
        });
    });

Working with a cache

We can retrieve items from a cache like so:

var profile = profileCache.get('/profiles/34');

profile.name; // 'John'

And get information about items in the cache:

var info = profileCache.info('/profiles/34');

info.isExpired; // false
// etc.

and information about the cache itself:

var info = profileCache.info();

info.size; // 2
info.maxAge; // 3600000
info.deleteOnExpire; // 'aggressive'
// etc.

Items are easily removed, and we can destroy out cache when we're done with it:

profileCache.remove('/profiles/34');

profileCache.get('/profiles/34'); // undefined

profileCache.destroy();

$angularCacheFactory.get('profileCache'); // undefined

See the API Documentation for more information on the available methods.

Using angular-cache with $http

Note The downside of letting $http handle caching for you is that it caches the responses (in string form) to your requests–not the JavaScript Object parsed from the response body. This means you can't interact with the data in the cache used by $http. See below for how to handle the caching yourself–giving you more control and the ability to interact with the cache (use it as a data store).

Configure $http to use a cache created by $angularCacheFactory by default:

app.run(function ($http, $angularCacheFactory) {

    $angularCacheFactory('defaultCache', {
        maxAge: 900000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
    });

    $http.defaults.cache = $angularCacheFactory.get('defaultCache');
});

app.service('myService', function ($http) {
    return {
        getDataById: function (id) {
            var deferred = $q.defer(),
                start = new Date().getTime();

            $http.get('api/data/' + id, {
                cache: true
            }).success(function (data) {
                console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
                deferred.resolve(data);
            });
            return deferred.promise;
        }
    };
});

app.controller('myCtrl', function (myService) {
    myService.getDataById(1)
        .then(function (data) {
            // e.g. "time taken for request: 2375ms"
            // Data returned by this next call is already cached.
            myService.getDataById(1)
                .then(function (data) {
                    // e.g. "time taken for request: 1ms"
                });
        });
});

Tell $http to use a cache created by $angularCacheFactory for a specific request:

app.service('myService', function ($http, $angularCacheFactory) {

    $angularCacheFactory('dataCache', {
        maxAge: 90000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
    });

    return {
        getDataById: function (id) {
            var deferred = $q.defer(),
                start = new Date().getTime();

            $http.get('api/data/' + id, {
                cache: $angularCacheFactory.get('dataCache')
            }).success(function (data) {
                console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
                deferred.resolve(data);
            });
            return deferred.promise;
        }
    };
});

app.controller('myCtrl', function (myService) {
    myService.getDataById(1)
        .then(function (data) {
            // e.g. "time taken for request: 2375ms"
            // Data returned by this next call is already cached.
            myService.getDataById(1)
                .then(function (data) {
                    // e.g. "time taken for request: 1ms"
                });
        });
});

Do your own caching while using the $http service:

app.service('myService', function ($http, $angularCacheFactory) {

    $angularCacheFactory('dataCache', {
        maxAge: 900000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
    });

    return {
        getDataById: function (id) {
            var deferred = $q.defer(),
                start = new Date().getTime(),
                dataCache = $angularCacheFactory.get('dataCache');

            // Now that control of inserting/removing from the cache is in our hands,
            // we can interact with the data in "dataCache" outside of this context,
            // e.g. Modify the data after it has been returned from the server and
            // save those modifications to the cache.
            if (dataCache.get(id)) {
                deferred.resolve(dataCache.get(id));
            } else {
                $http.get('api/data/' + id).success(function (data) {
                        console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
                        deferred.resolve(data);
                    });
            }
            return deferred.promise;
        }
    };
});

app.controller('myCtrl', function (myService) {
    myService.getDataById(1)
        .then(function (data) {
            // e.g. "time taken for request: 2375ms"
            // Data returned by this next call is already cached.
            myService.getDataById(1)
                .then(function (data) {
                    // e.g. "time taken for request: 1ms"
                });
        });
});

Using angular-cache with localStorage (or sessionStorage)

Using angular-cache in browsers that support localStorage:

app.service('myService', function ($angularCacheFactory) {

    // This cache will sync itself with localStorage if it exists, otherwise it won't. Every time the
    // browser loads this app, this cache will attempt to initialize itself with any data it had
    // already saved to localStorage (or sessionStorage if you used that).
    var myAwesomeCache = $angularCacheFactory('myAwesomeCache', {
        maxAge: 900000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive', // Items will be deleted from this cache right when they expire.
        storageMode: 'localStorage' // This cache will sync itself with `localStorage`.
    });
});

Using angular-cache in browsers that DON'T support localStorage:

Option 1 - Do nothing (the localStorage sync feature will be disabled)

Option 2 - Create/use a polyfill that provides the global localStorage and sessionStorage objects. angular-cache will attempt to use these if it finds them.

Option 3 - Tell angular-cache exactly which polyfill to use (also useful if you just want to use your own implementation/wrapper for localStorage):

app.service('myService', function ($angularCacheFactory) {

    var localStoragePolyfill = {
        getItem: function (key) { ... },
        setItem: function (key, value) { ... },
        removeItem: function (key) { ... }
    };

    // Always use the polyfill
    var myAwesomeCache = $angularCacheFactory('myAwesomeCache', {
        maxAge: 900000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive', // Items will be deleted from this cache right when they expire.
        storageMode: 'localStorage', // This cache will sync itself with `localStorage`.
        storageImpl: localStoragePolyfill // angular-cache will use this polyfill instead of looking for localStorage
    });

    // Conditionally use the polyfill
    var options = {
        maxAge: 900000, // Items added to this cache expire after 15 minutes.
        cacheFlushInterval: 3600000, // This cache will clear itself every hour.
        deleteOnExpire: 'aggressive', // Items will be deleted from this cache right when they expire.
        storageMode: 'localStorage' // This cache will sync itself with `localStorage`.
    };
    if (!window.localStorage) {
        options.storageImpl = localStoragePolyfill;
    }
    var myAwesomeCache = $angularCacheFactory('myAwesomeCache', options);
});

Documentation on the interface that must be implemented by any storageImpl polyfill used by angular-cache can be found on the W3C Recommendation page for webstorage. The interface itself looks like:

interface Storage {
  readonly attribute unsigned long length;
  DOMString? key(unsigned long index);
  getter DOMString getItem(DOMString key);
  setter creator void setItem(DOMString key, DOMString value);
  deleter void removeItem(DOMString key);
  void clear();
};

angular-cache cares only about these three methods:

One developer suggested using store.js–a wrapper and polyfill for localStorage. However, store.js has its own API that doesn't match that of the webstorage spec, so if you want to use store.js or any other 3rd-party polyfill then you'll need to create a wrapper for it if it doesn't have the same API as localStorage. For example:

var storeJsToStandard {
  getItem: store.get,
  setItem: store.set,
  removeItem: store.remove
};

$angularCacheFactory('myNewCache', {
  storageMode: 'localStorage',
  storageImpl: storeJsToStandard
});

See Configuration Options for information on the available configuration options.

Dynamically configure a cache

app.service('myService', function ($angularCacheFactory) {

    var cache = $angularCacheFactory('cache', {
        capacity: 100,
        maxAge: 300000
    });

    // Add 50 items here, for example

    cache.info(); // { ..., size: 50, capacity: 100, maxAge: 300000, ... }

    cache.setOptions({
        capacity: 30
    });

    cache.info(); // { ..., size: 30, capacity: 30, maxAge: 300000, ... }
    // notice that only the 30 most recently added items remain in the cache because
    // the capacity was reduced.

    // setting the second parameter to true will cause the cache's configuration to be
    // reset to defaults before the configuration passed into setOptions() is applied to
    // the cache
    cache.setOptions({
        cacheFlushInterval: 5500
    }, true);

    cache.info(); // { ..., size: 30, cacheFlushInterval: 5500,
                  //   capacity: 1.7976931348623157e+308, maxAge: null, ... }

    cache.put('someItem', 'someValue', { maxAge: 12000, deleteOnExpire: 'aggressive' });
    cache.info('someItem'); // { maxAge: 12000, deleteOnExpire: 'aggressive', isExpired: false, ... }
});

See AngularCache.setOptions(options).