How to define expiration time on Cache in Angular $cacheFactory

Problem

I read about the Angular '$cacheFactory' but could not find any documentation on setting an expiration date for cached content.

What if I want to cache all GET requests for 30 seconds, how to I define this in the '$cacheFactory' or do I need to extend the functionality myself.

Problem courtesy of: Adrian E

Solution

I faced the problem too. The default $cacheFactory have no time to live (TTL).

You will need to implement this yourself. But before, you could give a look around, to see if someone already did it :

This one look pretty complete - http://jmdobry.github.io/angular-cache/

If you really want to implement your own solution (by implementing your own $cacheFactory) and need some help, feel free to ask.

Hope it gave you some clue.

Solution courtesy of: Okazari

Discussion

for TTL 1h, see below example

add factory:

.factory('cacheInterceptor', ['$cacheFactory', function($cacheFactory) {
  var http_ttl_cache = {};
  return {
    request: function(config) {
      var N;
      if (config.timeToLive) {
        config.cache = true;
        N = config.timeToLive;
        delete config.timeToLive;
        if (new Date().getTime() - (http_ttl_cache[config.url] || 0) > N) {
          $cacheFactory.get('$http').remove(config.url);
          http_ttl_cache[config.url] = new Date().getTime();
        }
      }
      return config;
    }
  };
}])

then init in config push your interceptor. An interceptor is simply a regular service factory that is registered to that array.

.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {

  $httpProvider.interceptors.push('cacheInterceptor');

example of request

$http.get('/permissions.json', {timeToLive: Constant.timeToLive}).then(function(result){

Constant is:

.constant('Constant', {
  url: {
    logout: '/auth/logout'
  },
  timeToLive: 60*60*1000
})
Discussion courtesy of: miukki

I think @miukki answer's is great. Adding my modification to the request of @Vil

I modified the 'request' function of the 'cacheInterceptor' to use $timeout instead of relying on Date. It allows TTL to be more global for requests, So if one request sets a TTL and the 2nd doesn't but data is still in cached, it will still be used.

.factory('cacheInterceptor', ['$cacheFactory', '$timeout', function($cacheFactory, $timeout) {
  var ttlMap = {};
  return {
    request: function(config) {
      if (config.ttl) {
        var ttl = config.ttl;
        delete config.ttl;
        config.cache = true;

        // If not in ttlMap then we set up a timer to delete, otherwise there's already a timer.
        if (!ttlMap[config.url]) {
          ttlMap[config.url] = true;
          $timeout(ttl)
          .then(function() {
            $cacheFactory.get('$http').remove(config.url);          
            delete ttlMap[config.url];
          });
        }
      }
      return config;
    }
  };
}])
Discussion courtesy of: Yaron

This recipe can be found in it's original form on Stack Over Flow.