Como atualizar / invalidar o cache de $ resource em AngularJS


94

Eu tenho um recurso User $ simples que usa a implementação de cache $ http padrão assim:

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

Isso funciona muito bem, ou seja, meu servidor só é chamado uma vez em meu aplicativo, então o valor é obtido do cache.

Mas preciso atualizar o valor do servidor após uma determinada operação. Existe uma maneira fácil de fazer isso?

Obrigado.


1
Estou usando instável (1.1.5, mas acho que está lá desde 1.1.2) cache- {boolean|Cache}- Se verdadeiro, um cache $ http padrão será usado para armazenar a solicitação GET, caso contrário, se uma instância de cache construída com
Alexandre Bulté

1
estou tendo um problema semelhante, mas apenas durante o teste. como faço para impedir isso no nível do navegador?
chovy

Respostas:


116

Mantenha o booleano e obtenha o $httpcache:

var $httpDefaultCache = $cacheFactory.get('$http');

Então você pode controlá-lo como qualquer outro cache feito com $cacheFactory, uma instância de uso fornecida abaixo:

$httpDefaultCache.remove(key);
// Where key is the relative URL of your resource (eg: /api/user/current/51a9020d91799f1e9b8db12f)

52
Perfeito, obrigado! Exatamente o que eu estava procurando. Para aqueles que estão se perguntando, você pode chamar $ cacheFactory.get ('$ http'). Remove (key), com a chave sendo a URL relativa do seu recurso (ex: / api / user / current / 51a9020d91799f1e9b8db12f).
Alexandre Bulté

2
Na verdade, descobri que precisava especificar o url completo junto com quaisquer parâmetros de consulta ao chamar remove (). Estou faltando alguma coisa aqui?
shangxiao,

3
Tenho parâmetros de consulta dinâmicos. Existe uma maneira de acessar o url da $resourcefábrica?
Suzanshakya

1
Enquanto isso funciona. Pode ser mais complexo do que o necessário. Uma solução melhor seria se isso fosse implementado: github.com/angular/angular.js/issues/9064
KFunk

5
Para mim, $ cacheFactory.get ('$ http'). RemoveAll () resolveu, pois eu precisava limpar todos os dados armazenados em cache.
S. Baggy

18

Em vez de usar um argumento booleano na cachepropriedade de cada um, actionvocê pode passar uma instância de cache criada com $ cacheFactory sobre a qual você pode ter mais controle (ou seja, limpar o cache).

Exemplo de uso:

app.factory('Todos', function($resource, $cacheFactory) {
    var cache = $cacheFactory('todo');
    return $resource(apiBaseUrl + '/todos/:id', { id: '@id' }, {
        'get': { method: 'GET', cache: cache  },
        'query': { method: 'GET', cache: cache, isArray: true }
    });
});

Obrigado. Eu vi isso também, mas estava procurando uma maneira "padrão" de fazer isso antes de seguir por esse caminho ...
Alexandre Bulté 12/06/2013

1
parece uma abordagem muito "padrão" em conformidade com a "forma angular" :)
Variante

1
Você está certo. Eu quis dizer uma abordagem com o cache de recurso $ padrão.
Alexandre Bulté

6

Eu encontrei este tópico procurando por algo semelhante, mas descobri que $ resource irá gerenciar o cache para você automaticamente, então não há necessidade de forçar a limpeza do cache.

A ideia é que se você tiver um recurso que possa consultar, essa resposta da consulta será armazenada em cache, mas se você salvar algo para esse mesmo recurso, os dados armazenados em cache anteriormente devem ser inválidos, portanto, são limpos para você. Faz sentido que funcione dessa maneira.

Aqui está um código que uso para fazer isso (você pode ignorar a parte possivelmente estranha da criação de fábrica e prestar atenção ao corpo da "classe").

'use strict';

sampleApp.players.$ng.factory('sampleApp.players.PlayerService', [
    '$log',
    '$resource',
    sampleApp.players.PlayerService = function ($log, $resource) {
        var service = {};

        $log.info('Creating player resource.');
        var Player = $resource('/api/players', {}, {query: {
            isArray: true,
            cache: true,
            method: 'GET'
        }});

        service.addPlayer = function(playerName) {
            $log.info('Saving a new player.');
            return new Player({name: playerName}).$save();
        };

        service.listPlayers = function () {
            $log.info('Fetching players.');
            return Player.query();
        };

        return service;
    }]);

Se você chamar a função listPlayers várias vezes, a primeira chamada fará uma solicitação http get e todas as chamadas subsequentes serão armazenadas em cache. Se você chamar addPlayer, uma postagem http será executada conforme o esperado e, em seguida, a próxima chamada para listPlayers executará um http get (não armazenado em cache).

Isso o mantém fora do negócio de gerenciar o cache de outra pessoa ($ http) e tentar acompanhar quais URLs estão sendo usados ​​para solicitações e quais estão limpando caches nos momentos certos.

Suponho que a moral da história aqui é trabalhar com a biblioteca e tudo ficará bem ... exceto por quaisquer bugs ou recursos incompletos, mas o Angular não tem nenhum desses;)

ps Está tudo em execução no AngularJS 1.2.0.


2
Sim, eu entendo e reconheço que em condições "normais" o recurso Angular sabe como e quando invalidar o cache, e funciona perfeitamente. Mas meu caso de uso era um pouco diferente: eu queria forçar uma atualização porque o Angular não tinha como saber se uma atualização era necessária - o objeto de usuário sendo modificado fora do aplicativo Angular.
Alexandre Bulté

3
Alguém pode apontar onde isso está documentado? Eu li sobre isso antes no Stack Overflow, mas não consigo encontrar qualquer menção a isso na documentação. Também tentei no meu aplicativo, mas talvez tenha feito algo errado ao longo do caminho ...
Sunil D.

1
No entanto, não parece funcionar com $ delete. A próxima chamada será puxada do cache novamente e o item excluído reaparecerá. Alguém pode confirmar?
Lukus

Isso não funcionará ngResource NÃO MANUSEIE a invalidação de cache, por exemplo: stackoverflow.com/questions/25117388/…
HugoPoi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.