jmdobry / angular-cache

angular-cache is a very useful replacement for the Angular 1 $cacheFactory.
http://jmdobry.github.io/angular-cache
MIT License
1.39k stars 156 forks source link

Force cache refresh #34

Closed ghost closed 11 years ago

ghost commented 11 years ago

Is it possible to actively trigger cache refreshing of a specific $resource request?

max-kruse commented 11 years ago

+1

jmdobry commented 11 years ago

Can you paste a snippet of your code here where you are using angular-cache with $resource?

jmdobry commented 11 years ago

If I assume correctly about what you're trying to do, then you've got something like:

factory('User', function($resource) {
    return $resource(endpoint + '/user/current/:projectId', {}, {
        get: {
            cache: true, // This caches the response to the request
            method: 'GET'
        }
    });
});

But you want to force a refresh of the cache. Well, if you know the name of the cache ($http uses a cache named "$http" by default) then you can call $cacheFactory.get('$http').removeAll(); and that will clear the cache that $http uses by default.

If you specified something like $http.defaults.cache = $angularCacheFactory('myCache'); then you can do $angularCacheFactory.get('myCache').removeAll();.

If you know the key of the item that needs to be removed/refreshed just do $angularCacheFactory('myCache').remove(keyToBeRemoved); or replace it with a fresh value from the server.

With $resource you can use it like this:

app.factory('myService', function($resource, $angularCacheFactory) {
    var myCache = $angularCacheFactory('myCache');
    var User = $resource('/user/:userId', {userId:'@id'});

    return {
        getResource: function(userId) {
            var user;
            if (shouldRefreshCache) {
                // myCache.removeAll();
                // or just replace the value for userId with a fresh value from the server
                myCache.remove('http://mydomain.com/user/' + userId);
                user = User.get({userId:userId});
                myCache.put(userId, user);
                return user;
            } else {
                user = myCache.get(userId);
                if (!user) {
                    user = User.get({userId:userId});
                    myCache.put(userId, user);   
                }
                return user;
            }
        }
    };
});
jmdobry commented 11 years ago

You can now also do $angularCacheFactory.clearAll() to clear the contents of all caches owned by $angularCacheFactory.

See #38

jmdobry commented 11 years ago

Consider this question answered.

nooysters commented 10 years ago

Hi, I am trying to do this as in your example but the returned cached resource is an empty object, completely empty, not just an unresolved promise. What am I doing wrong?

var productService = angular.module('productService', ['ngResource']); productService.factory('Product', ['$resource','$angularCacheFactory', function($resource, $angularCacheFactory) {

var productCache = $angularCacheFactory('productDataCache', {
    capacity: 1,
    maxAge: 30000,
    deleteOnExpire: 'aggressive',
});

var productResource = $resource('/customize/product/:Pid',{}, { update: { method: 'POST', url: '/customize/product/:Action/:Pid', params: {Action: 'update', Pid: '@pid'} }, destroy: { method: 'POST', url: '/customize/product/:Action/:Pid', params: {Action: 'delete', Pid: '@pid'} }, create: { url: '/customize/product/:Action/:Type', params: {Action: 'create', Type: '@type'} } } );

return {
  getProductResource: function(type) {
     var product;
     product = productCache.get('activeProduct');

     if(!product) {
       product = productResource.create();
       productCache.put('activeProduct', product);

     }
     return product;
  }
};

}]);

in controller:

$scope.product = Product.getProductResource();

jmdobry commented 10 years ago

product = productResource.create(); is an asynchronous operation. The next line productCache.put('activeProduct', product); will be executed before the server has responded with the created product. Modify your code to be asynchronous:

if(!product) {
  return productResource.create().then(function (product) {
    return productCache.put('activeProduct', product);
  });
} else {
  return product;
}
nooysters commented 10 years ago

Thank you so much! worked like a charm with one small change or calling then on the $promise object.

     if(!product) {
       return productResource.create().$promise.then(function (product) {
         return productCache.put('activeProduct', product);
      });
    } else {
     return product;
    }