Invalidate $resource Cache After Post Request

二次信任 提交于 2020-01-20 16:51:00

问题


I am using $resource and caching the results of get requests. My problem is that, after post requests, the cache is not being invalidated.

Here is the return value from the service:

return $resource('http://url.com/api/url/:id', {}, {
'query' : {
      method : 'GET',
      isArray:true,
      cache : true
    },
'get' : {
  method : 'GET',
  cache : false
}  
})

Here is the save method I am using inside my controller. As you can see, I'm using the callback on the post request to recalculate the query/list of nouns.

var newNoun = new Noun($scope.noun);
newNoun.$save(function(x) {
  $scope.nouns = Noun.query();
});

I would like to invalidate the cache after calling post or another non-get method. How could I do this? Is this already built into $resource or do I need to implement it on my own?


回答1:


You could create a wrapper service to do the caching like you want, for example:

app.factory('cachedResource', function ($resource, $cacheFactory) {
  var cache = $cacheFactory('resourceCache');

  var interceptor = {
    response: function (response) {
      cache.remove(response.config.url);
      console.log('cache removed', response.config.url);
      return response;
    }
  };

  return function (url, paramDefaults, actions, options) {
    actions = angular.extend({}, actions, {
      'get':    { method: 'GET', cache: cache },
      'query':  { method: 'GET', cache: cache, isArray: true },
      'save':   { method: 'POST', interceptor: interceptor },
      'remove': { method: 'DELETE', interceptor: interceptor },
      'delete': { method: 'DELETE', interceptor: interceptor },
    });

    return $resource(url, paramDefaults, actions, options);
  };
});

Then replace any $resource with cachedResource.

Example plunker: http://plnkr.co/edit/lIQw4uogcoMpcuHTWy2U?p=preview




回答2:


While @runTarm's answer above is great, it does not allow actions to be easily customized from the inheriting service, e.g. the following would not be possible:

app.factory('Steps', function (CachedResource) {
    return CachedResource('/steps/:stepId', {}, {
        save: { method: 'POST', params: { stepId: '@stepId' } }
    });
});

In this case, this definition of save would be replaced by the one present in CachedResource.

Solution

But it can be fixed easily from Angular 1.4 by replacing

actions = angular.extend({}, actions, {

with

actions = angular.merge({}, actions, {

so that both objects are deep-merged.

Even better solution

In the above scenario, action options defined in CachedResource would be preferred over custom configuration in inheriting services. To fix that, switch the order of arguments passed to merge:

actions = angular.merge({}, { /* default options get, query, etc. */ }, actions);

With this solution, the following will work as expected (i.e. use DESTROY instead of default DELETE when calling remove):

app.factory('Steps', function (CachedResource) {
    return CachedResource('/steps/:stepId', {}, {
        remove: { method: 'DESTROY' }
    });
}); 



回答3:


$resource is using the default cache for $http.

You can access it using: $cacheFactory.get('$http')

You can remove a key value pair, using the returned caches remove({string} key) method.


E.g.:

var key = '...the key you want to remove, e.g. `/nouns/5`...';
$cacheFactory.get('$http').remove(key);


来源:https://stackoverflow.com/questions/25117388/invalidate-resource-cache-after-post-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!