Eine HTTP-Dienstantwort "Get" in AngularJS zwischenspeichern?


211

Ich möchte in der Lage sein, einen benutzerdefinierten AngularJS-Dienst zu erstellen, der eine HTTP-Anforderung "Get" erstellt, wenn sein Datenobjekt leer ist und das Datenobjekt bei Erfolg auffüllt.

Wenn dieser Dienst das nächste Mal aufgerufen wird, möchte ich den Aufwand für das erneute Ausführen der HTTP-Anforderung umgehen und stattdessen das zwischengespeicherte Datenobjekt zurückgeben.

Ist das möglich?

Antworten:


315

In Angulars $ http ist ein Cache integriert . Laut den Dokumenten:

cache - {boolean | Object} - Ein boolescher Wert oder ein Objekt, das mit $ cacheFactory erstellt wurde, um das Caching der HTTP-Antwort zu aktivieren oder zu deaktivieren. Weitere Informationen finden Sie unter $ http Caching .

Boolescher Wert

So können Sie in seinen Optionen cacheauf true setzen :

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

oder, wenn Sie den Konfigurationstyp bevorzugen:

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

Cache-Objekt

Sie können auch eine Cache-Factory verwenden:

var cache = $cacheFactory('myCache');

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

Sie können es selbst mit $ cacheFactory implementieren (besonders praktisch, wenn Sie $ resource verwenden):

var cache = $cacheFactory('myCache');

var data = cache.get(someKey);

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

47
Frage: Wozu werden zwischengespeicherte Daten in $ cacheFactory gespeichert? Warum nicht einfach in einem lokalen Objekt im Service speichern? Irgendwelche guten Gründe?
Spock

7
Überprüfen Sie dies heraus. Es gibt Ihnen eine Menge Anpassbarkeit einschließlich local Unterstützung, Timeout - Unterstützung, alle Arten von Leckereien http://jmdobry.github.io/angular-cache/
Erik Donohoo

4
Ich bin besonders neugierig auf den Statuscode 304 - funktioniert der Browser-Cache, ohne den Cache zu aktivieren: true? Wenn nicht, funktioniert Cache: True? Ist das Caching permanent oder befindet es sich nur im RAM und wird beim Schließen der Seite entladen?
Sasha.sochka

3
Gibt es eine Möglichkeit, ein Zeitlimit für diesen Cache festzulegen, ohne es manuell zu implementieren?
Mark

11
@Spock, $ cacheFactory selbst ist ein Dienst, der für mehrere Controller und Winkelkomponenten verwendet werden kann. Es kann als generischer API-Dienst verwendet werden, um alle Ihre $ https in einem einzigen Dienstobjekt zwischenzuspeichern, anstatt für jedes einzelne unterschiedliche Dienstobjekte zu haben.
Nirav Gandhi

48

Ich denke, es gibt jetzt einen noch einfacheren Weg. Dies ermöglicht das grundlegende Caching für alle $ http-Anforderungen (die $ resource erbt):

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

46
Sie möchten kaum jede einzelne http-Anfrage zwischenspeichern. Ich sehe nicht, wann das jemals der Fall sein würde?
Spock

1
Jede App / jedes Modul ist anders, nein?!
Rodrigo-Silveira

13
Wenn Sie die meisten Anforderungen zwischenspeichern möchten, ist es praktisch, den Standardwert auf true zu setzen.
Adrian Lynch

12

Eine einfachere Möglichkeit, dies in der aktuellen stabilen Version (1.0.6) zu tun, erfordert viel weniger Code.

Fügen Sie nach dem Einrichten Ihres Moduls eine Fabrik hinzu:

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

Jetzt können Sie dies an Ihren Controller übergeben:

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

Ein Nachteil ist, dass die Schlüsselnamen auch automatisch eingerichtet werden, was das Löschen schwierig machen kann. Hoffentlich fügen sie etwas hinzu, um Schlüsselnamen zu erhalten.


7

Schauen Sie sich den Winkel-Cache der Bibliothek an, wenn Sie das integrierte Caching von $ http mögen, aber mehr Kontrolle wünschen. Sie können es verwenden, um den $ http-Cache nahtlos mit einer regelmäßigen Lebensdauer der Lebensdauer und der Option zu erweitern, den Cache für localStorage beizubehalten, damit er sitzungsübergreifend verfügbar ist.

FWIW bietet außerdem Tools und Muster, mit denen Sie Ihren Cache zu einem dynamischeren Datenspeicher machen können, mit dem Sie als POJOs interagieren können, und nicht nur mit den Standard-JSON-Zeichenfolgen. Ich kann das Dienstprogramm dieser Option noch nicht kommentieren.

(Dann Hinzu kommt, dass, im Zusammenhang Bibliothek Winkeldaten sind eine Art Ersatz für $ Ressourcen- und / oder Restangular, und hängen von Winkel-cache) .


3
Bitte beachten Sie, dass dies angular-datajetzt veraltet ist. Der neueste Stand ist js-data-angular js-data.io/v1.8.0/docs/js-data-angular
demisx

Die Angular-Cache-Bibliothek verfügt über die Funktionen, die in Angulars $ cacheFactory integriert sein sollten. Die integrierte Lösung scheint fast nutzlos zu sein, da bestimmte Caches nur eingeschränkt ablaufen können. Die Angular-Cache-Factory war eine der am einfachsten zu implementierenden Bibliotheken von Drittanbietern.
Darryl

5

Da AngularJS-Fabriken Singletons sind , können Sie das Ergebnis der http-Anforderung einfach speichern und abrufen, wenn Ihr Dienst das nächste Mal in etwas injiziert wird.

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

Ich habe eine Frage, wie man prüft, ob GET fehlgeschlagen ist und in diesem Fall die $ resource ... query ()
robert

@robert Sie können das zweite Argument der .then-Methode überprüfen oder noch besser den .catch-Rückruf verwenden. Zum Beispiel $ http .get (url) .then (successCallback, failCallback) oder $ http .get (url) .then (successCallback, failCallback) .catch (errorCallback) Der Fehlerrückruf wird ausgeführt, selbst wenn im failCallback etwas Schlimmes passiert , obwohl es üblicher ist, den fehlgeschlagenen Rückruf überhaupt zu vermeiden und .then (Erfolg) .catch (manageRequestFail) zu verwenden. Hoffe das hilft die Idee zu verstehen, mehr Infos in der eckigen $ http Dokumentation.
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}
        });
    }]);

Setzen Sie den Cache auf true.


Dies wäre genauso sicher wie die Client-Anwendung mit dem Browser selbst, genau wie jede andere Web-App.
Bhantol

-1

In Angular 8 können wir Folgendes tun:

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

Sie können es so nennen:

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


});

Der obige Code speichert das Ergebnis der Remote-API beim ersten Aufruf im Cache, damit es bei weiteren Anforderungen an diese Methode verwendet werden kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.