¿Caché una respuesta de servicio HTTP 'Get' en AngularJS?


211

Quiero poder crear un servicio personalizado de AngularJS que realice una solicitud HTTP 'Obtener' cuando su objeto de datos esté vacío y llene el objeto de datos con éxito.

La próxima vez que se realice una llamada a este servicio, me gustaría omitir la sobrecarga de realizar nuevamente la solicitud HTTP y, en su lugar, devolver el objeto de datos en caché.

es posible?

Respuestas:


315

$ Http de Angular tiene un caché incorporado . Según los documentos:

cache - {boolean | Object} - Un valor booleano u objeto creado con $ cacheFactory para habilitar o deshabilitar el almacenamiento en caché de la respuesta HTTP. Vea $ http Caching para más información .

Valor booleano

Entonces puede establecerlo cacheen verdadero en sus opciones:

$http.get(url, { cache: true}).success(...);

o, si prefiere el tipo de llamada de configuración:

$http({ cache: true, url: url, method: 'GET'}).success(...);

Objeto de caché

También puede usar una fábrica de caché:

var cache = $cacheFactory('myCache');

$http.get(url, { cache: cache })

Puede implementarlo usted mismo usando $ cacheFactory (especialmente útil cuando usa $ resource):

var cache = $cacheFactory('myCache');

var data = cache.get(someKey);

if (!data) {
   $http.get(url).success(function(result) {
      data = result;
      cache.put(someKey, data);
   });
}

47
Pregunta: ¿cuál es el punto de guardar los datos en caché en $ cacheFactory ... por qué no simplemente guardarlos en un objeto local en el Servicio? ¿Alguna buena razón?
Spock

77
Mira esto. Le brinda mucha capacidad de personalización, incluido el soporte localStorage, el tiempo de espera, todo tipo de
cosas

44
Tengo especial curiosidad sobre el código de estado 304: ¿funciona el caché del navegador sin habilitar el caché: verdadero? Si no, ¿cache: true lo hace funcionar? ¿El almacenamiento en caché es permanente o solo está en la RAM y se descarga cuando se cierra la página?
sasha.sochka

3
¿Alguna forma de especificar un límite de tiempo en este caché sin implementarlo manualmente?
Mark

11
@Spock, $ cacheFactory en sí mismo es un servicio que se puede usar en múltiples controladores y componentes angulares. Se puede usar como un servicio de API genérico para almacenar en caché todos sus $ http en un único obj de servicio en lugar de tener diferentes objetos de servicio para cada uno de ellos.
Nirav Gandhi

48

Creo que hay una manera aún más fácil ahora. Esto permite el almacenamiento en caché básico para todas las solicitudes $ http (que $ resource hereda):

 var app = angular.module('myApp',[])
      .config(['$httpProvider', function ($httpProvider) {
            // enable http caching
           $httpProvider.defaults.cache = true;
      }])

46
Apenas desea almacenar en caché cada solicitud http. ¿No veo cuándo sería ese el caso?
Spock

1
Cada aplicación / módulo es diferente, ¿no?
rodrigo-silveira

13
Si desea almacenar en caché la mayoría de las solicitudes, es útil establecer el valor predeterminado en verdadero.
Adrian Lynch

12

Una forma más fácil de hacer esto en la versión estable actual (1.0.6) requiere mucho menos código.

Después de configurar su módulo, agregue una fábrica:

var app = angular.module('myApp', []);
// Configure routes and controllers and views associated with them.
app.config(function ($routeProvider) {
    // route setups
});
app.factory('MyCache', function ($cacheFactory) {
    return $cacheFactory('myCache');
});

Ahora puede pasar esto a su controlador:

app.controller('MyController', function ($scope, $http, MyCache) {
    $http.get('fileInThisCase.json', { cache: MyCache }).success(function (data) {
        // stuff with results
    });
});

Una desventaja es que los nombres clave también se configuran automáticamente, lo que podría dificultar su eliminación. Esperemos que agreguen de alguna manera para obtener nombres clave.


7

Eche un vistazo a la biblioteca de caché angular si le gusta el almacenamiento en caché incorporado de $ http pero quiere más control. Puede usarlo para aumentar sin problemas el caché de $ http con purgas periódicas de tiempo de vida y la opción de mantener el caché en localStorage para que esté disponible en todas las sesiones.

FWIW, también proporciona herramientas y patrones para convertir su caché en un tipo de almacén de datos más dinámico con el que puede interactuar como POJO, en lugar de solo las cadenas JSON predeterminadas. No puedo comentar sobre la utilidad de esa opción todavía.

(Luego, además de eso, los datos angulares de la biblioteca relacionada son una especie de reemplazo de $ resource y / o Restangular, y dependen de la memoria caché angular).


3
Tenga en cuenta que angular-dataahora está en desuso. La última js-data-angular versión
demisx

La biblioteca de caché angular tiene las características que deberían haberse incorporado en $ cacheFactory de Angular. La solución integrada parece casi inútil debido a sus limitaciones para poder caducar cachés específicos. La fábrica de caché angular también fue una de las bibliotecas de terceros más fáciles de implementar.
Darryl

5

Como las fábricas de AngularJS son singletons , simplemente puede almacenar el resultado de la solicitud http y recuperarlo la próxima vez que su servicio se inyecte en algo.

angular.module('myApp', ['ngResource']).factory('myService',
  function($resource) {
    var cache = false;
    return {
      query: function() {
        if(!cache) {
          cache = $resource('http://example.com/api').query();
        }
        return cache;
      }
    };
  }
);

Tengo una pregunta sobre cómo verificar si GET falló y en ese caso no poner en caché el $ resource ... query ()
robert

@robert puede verificar el segundo argumento del método .then o mejor aún, use la devolución de llamada .catch. Por ejemplo $ http .get (url) .then (successCallback, failCallback) o $ http .get (url) .then (successCallback, failCallback) .catch (errorCallback) La devolución de llamada de error se ejecutará incluso si algo malo sucede en el failCallback , aunque es más común evitar la devolución de llamada fallida y usar .then (éxito) .catch (manageRequestFail). Espero que ayude a comprender la idea, más información en la documentación angular de $ http.
Faito

2
angularBlogServices.factory('BlogPost', ['$resource',
    function($resource) {
        return $resource("./Post/:id", {}, {
            get:    {method: 'GET',    cache: true,  isArray: false},
            save:   {method: 'POST',   cache: false, isArray: false},
            update: {method: 'PUT',    cache: false, isArray: false},
            delete: {method: 'DELETE', cache: false, isArray: false}
        });
    }]);

configura el caché para que sea verdadero.


Esto sería tan seguro como la aplicación cliente dentro del navegador como cualquier otra aplicación web.
Bhantol

-1

En Angular 8 podemos hacer así:

import { Injectable } from '@angular/core';
import { YourModel} from '../models/<yourModel>.model';
import { UserService } from './user.service';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class GlobalDataService {

  private me: <YourModel>;

  private meObservable: Observable<User>;

  constructor(private yourModalService: <yourModalService>, private http: HttpClient) {

  }

  ngOnInit() {

  }


  getYourModel(): Observable<YourModel> {

    if (this.me) {
      return of(this.me);
    } else if (this.meObservable) {
      return this.meObservable;
    }
    else {
      this.meObservable = this.yourModalService.getCall<yourModel>() // Your http call
      .pipe(
        map(data => {
          this.me = data;
          return data;
        })
      );
      return this.meObservable;
    }
  }
}

Puedes llamarlo así:

this.globalDataService.getYourModel().subscribe(yourModel => {


});

El código anterior almacenará en caché el resultado de la API remota en la primera llamada para que pueda usarse en solicitudes adicionales a ese método.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.