Inserire nella cache una risposta di servizio HTTP "Get" in AngularJS?


211

Voglio essere in grado di creare un servizio AngularJS personalizzato che effettua una richiesta HTTP "Get" quando il suo oggetto dati è vuoto e popola l'oggetto dati in caso di successo.

La prossima volta che viene effettuata una chiamata a questo servizio, vorrei bypassare il sovraccarico di effettuare nuovamente la richiesta HTTP e restituire invece l'oggetto dati memorizzato nella cache.

È possibile?

Risposte:


315

$ Http di Angular ha una cache integrata . Secondo i documenti:

cache - {booleano | Oggetto} - Un valore booleano o un oggetto creato con $ cacheFactory per abilitare o disabilitare la memorizzazione nella cache della risposta HTTP. Vedi $ http Caching per maggiori informazioni .

Valore booleano

Quindi puoi impostare cachesu true nelle sue opzioni:

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

oppure, se si preferisce il tipo di configurazione della chiamata:

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

Oggetto cache

Puoi anche usare una cache factory:

var cache = $cacheFactory('myCache');

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

Puoi implementarlo tu stesso usando $ cacheFactory (specialmente a mano quando usi $ 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
Domanda: qual è il punto di salvare i dati memorizzati nella cache in $ cacheFactory .. perché non salvarli in un oggetto locale nel servizio? Qualche buona ragione?
Spock,

7
Controllalo. Ti dà un sacco di personalizzazione tra cui supporto localStorage, supporto timeout, tutti i tipi di chicche http://jmdobry.github.io/angular-cache/
Erik Donohoo

4
Sono particolarmente curioso del codice di stato 304 - la cache del browser funziona senza abilitare la cache: vero? In caso contrario, cache: true lo fa funzionare? La memorizzazione nella cache è permanente o è solo nella RAM e viene scaricata alla chiusura della pagina?
sasha.sochka,

3
Un modo per specificare un limite di tempo su questa cache senza implementarlo manualmente?
Segna il

11
@Spock, $ cacheFactory stesso è un servizio che può essere utilizzato su più controller e componenti angolari. Può essere utilizzato come un servizio API generico per memorizzare nella cache tutti i $ http in un unico obj di servizio anziché avere oggetti di servizio diversi per ognuno di essi.
Nirav Gandhi,

48

Penso che ci sia un modo ancora più semplice adesso. Ciò abilita la memorizzazione nella cache di base per tutte le richieste $ http (che $ risorse eredita):

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

46
Difficilmente vuoi memorizzare nella cache ogni singola richiesta http. Non vedo quando sarebbe mai il caso?
Spock,

1
Ogni app / modulo è diverso, no ?!
rodrigo-silveira,

13
Se si desidera memorizzare nella cache la maggior parte delle richieste, è utile impostare il valore predefinito su true.
Adrian Lynch,

12

Un modo più semplice per farlo nell'attuale versione stabile (1.0.6) richiede molto meno codice.

Dopo aver configurato il modulo aggiungere una fabbrica:

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

Ora puoi passare questo nel tuo controller:

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

Uno svantaggio è che anche i nomi delle chiavi vengono impostati automaticamente, il che potrebbe complicarne la cancellazione. Spero che aggiungano in qualche modo per ottenere i nomi delle chiavi.


7

Controlla la libreria angular-cache se ti piace la cache integrata di $ http ma desideri un maggiore controllo. È possibile utilizzarlo per aumentare senza problemi la cache $ http con eliminazioni periodiche time-to-live e l'opzione di persistere la cache in localStorage in modo che sia disponibile tra le sessioni.

Inoltre, fornisce anche strumenti e schemi per trasformare la cache in una sorta di archivio di dati più dinamico con cui è possibile interagire come POJO, anziché solo le stringhe JSON predefinite. Non posso ancora commentare l'utilità di quell'opzione.

(Inoltre, i dati angolari della libreria correlata sono una sorta di sostituto di $ resource e / o Restangular e dipendono dalla cache angolare.)


3
Si noti che angular-dataora è obsoleto. L'ultima è js-data-angular js-data.io/v1.8.0/docs/js-data-angular
demisx,

La libreria di cache angolare ha le funzionalità che avrebbero dovuto essere integrate in $ cacheFactory di Angular. La soluzione integrata sembra quasi inutile dati i suoi limiti nella possibilità di far scadere cache specifiche. La fabbrica della cache angolare era anche una delle librerie di terze parti più facili da implementare.
Darryl,

5

Poiché le fabbriche AngularJS sono singole , puoi semplicemente archiviare il risultato della richiesta http e recuperarlo la prossima volta che il tuo servizio viene iniettato in qualcosa.

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

Ho una domanda su come verificare se GET non è riuscito e in tal caso non mettere nella cache $ resource ... query ()
robert

@robert puoi controllare il secondo argomento del metodo .then o, meglio ancora, usare il callback .catch. Ad esempio $ http .get (url) .then (successCallback, failCallback) o $ http .get (url) .then (successCallback, failCallback) .catch (errorCallback) La richiamata dell'errore verrà eseguita anche se si verifica qualcosa di brutto in failCallback , sebbene sia più comune evitare del tutto il callback e utilizzare .then (success) .catch (manageRequestFail). Spero che aiuti a cogliere l'idea, maggiori informazioni nella documentazione angolare $ 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}
        });
    }]);

imposta la cache come vera.


Questo sarebbe sicuro come l'applicazione client all'interno del browser stesso come qualsiasi altra app web.
Bhantol,

-1

In Angular 8 possiamo fare così:

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;
    }
  }
}

Puoi chiamarlo così:

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


});

Il codice sopra memorizza nella cache il risultato dell'API remota alla prima chiamata in modo che possa essere utilizzato su ulteriori richieste a quel metodo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.