Cómo actualizar / invalidar $ resource cache en AngularJS

94

Tengo un recurso User $ simple que usa la implementación de caché $ http predeterminada así:

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

Esto funciona muy bien, es decir, mi servidor solo se llama una vez en mi aplicación, luego el valor se obtiene del caché.

Pero necesito actualizar el valor del servidor después de una determinada operación. ¿Existe una forma sencilla de hacerlo?

Gracias.

Alexandre Bulté
fuente
1
Estoy usando inestable (1.1.5 pero creo que está ahí desde 1.1.2) cache- {boolean|Cache}- Si es verdadero, se usará una caché $ http predeterminada para almacenar en caché la solicitud GET; de lo contrario, si se creó una instancia de caché con
Alexandre Bulté
1
Estoy teniendo un problema similar pero solo al realizar la prueba. ¿Cómo rompo esto a nivel del navegador?
Chovy

Respuestas:

116

Mantenga el booleano y obtenga el $httpcaché:

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

Luego, puede controlarlo como cualquier otro caché creado con $cacheFactoryuna instancia de uso que se proporciona a continuación:

$httpDefaultCache.remove(key);
// Where key is the relative URL of your resource (eg: /api/user/current/51a9020d91799f1e9b8db12f)
Anthonny
fuente
52
¡Perfecto, gracias! Exactamente lo que estaba buscando. Para aquellos que se pregunten, pueden llamar a $ cacheFactory.get ('$ http'). Remove (key), siendo la clave la URL relativa de su recurso (por ejemplo: / api / user / current / 51a9020d91799f1e9b8db12f).
Alexandre Bulté
2
En realidad, descubrí que necesitaba especificar la URL completa junto con los parámetros de consulta al llamar a remove (). ¿Me estoy perdiendo de algo?
shangxiao
3
Tengo parámetros de consulta dinámica. ¿Hay alguna forma de acceder a la URL desde $resourcefábrica?
suzanshakya
1
Mientras esto funciona. Puede ser más complejo de lo necesario. Una mejor solución sería si esto se implementara: github.com/angular/angular.js/issues/9064
KFunk
5
Para mí, $ cacheFactory.get ('$ http'). RemoveAll () hizo el truco, ya que necesitaba borrar todos los datos almacenados en caché.
S. Baggy
18

En lugar de utilizar un argumento booleano en la cachepropiedad de cada actionuno, puede pasar una instancia de caché creada con $ cacheFactory sobre la que puede tener más control (es decir, borrar la caché).

Uso de ejemplo:

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 }
    });
});
Variante
fuente
Gracias. También vi eso, pero estaba buscando una forma "estándar" de hacerlo antes de seguir ese camino ...
Alexandre Bulté
1
parece un enfoque muy "estándar" que se ajusta a la "forma angular" :)
Variante
1
Tienes razón. Me refiero a un enfoque con el caché de recursos $ estándar.
Alexandre Bulté
6

Encontré este hilo en busca de algo similar, pero descubrí que $ resource administrará el caché automáticamente, por lo que no es necesario forzar el borrado del caché.

La idea es que si tiene un recurso que puede consultar, esa respuesta de consulta se almacenará en caché, pero si guarda algo para ese mismo recurso, los datos almacenados en caché previamente deben ser inválidos, por lo que se borrará para usted. Tiene sentido que funcione de esta manera.

Aquí hay un código que utilizo para hacer esto (puede ignorar la parte de creación de fábrica posiblemente de aspecto extraño y prestar atención al cuerpo de la "clase").

'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;
    }]);

Si llama a la función listPlayers varias veces, la primera llamada realiza una solicitud http get y todas las llamadas posteriores se almacenan en caché. Sin embargo, si llama a addPlayer, se realiza una publicación http como se esperaba, y luego la siguiente llamada a listPlayers realizará una obtención http (no almacenada en caché).

Esto lo mantiene fuera del negocio de administrar el caché de otra persona ($ http) y tratar de mantenerse al día con las URL que se utilizan para las solicitudes y las que se borran de los cachés en el momento adecuado.

Supongo que la moraleja de la historia aquí es trabajar con la biblioteca y todo estará bien ... excepto por errores o características incompletas, pero Angular no tiene ninguno de esos;)

ps Todo esto se ejecuta en AngularJS 1.2.0.

usuario605331
fuente
2
Sí, entiendo y reconozco que en condiciones "normales" el recurso Angular sabe cómo y cuándo invalidar la caché, y funciona perfectamente. Pero mi caso de uso fue ligeramente diferente: quería forzar una actualización porque Angular no tenía forma de saber que se necesitaba una actualización: el objeto de usuario se estaba modificando fuera de la aplicación Angular.
Alexandre Bulté
3
¿Alguien puede señalar dónde está documentado esto? He leído sobre esto antes en Stack Overflow, pero no puedo encontrar ninguna mención al respecto en la documentación. También lo probé en mi aplicación, pero tal vez hice algo mal en el camino ...
Sunil D.
1
Sin embargo, no parece funcionar con $ delete. La siguiente llamada se extraerá de la memoria caché nuevamente y el elemento eliminado volverá a aparecer. ¿Alguien puede confirmar?
Lukus
Esto no funcionará ngResource NO MANEJA la invalidación de caché, vaya aquí, por ejemplo: stackoverflow.com/questions/25117388/…
HugoPoi