Pamięć podręczna odpowiedzi HTTP „Get” w AngularJS?

211

Chcę mieć możliwość utworzenia niestandardowej usługi AngularJS, która wysyła żądanie HTTP „Get”, gdy jego obiekt danych jest pusty i zapełnia obiekt danych w przypadku powodzenia.

Przy następnym wywołaniu tej usługi chciałbym pominąć narzut związany z ponownym wysyłaniem żądania HTTP i zamiast tego zwrócić buforowany obiekt danych.

czy to możliwe?

Gavriguy
źródło

Odpowiedzi:

315

Kątowe na $ http posiada pamięć wbudowaną . Według dokumentów:

cache - {boolean | Object} - Wartość logiczna lub obiekt utworzony za pomocą $ cacheFactory w celu włączenia lub wyłączenia buforowania odpowiedzi HTTP. Aby uzyskać więcej informacji, zobacz $ http Caching .

Wartość logiczna

Więc można ustawić cache, aby prawda w jego opcji:

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

lub, jeśli wolisz typ konfiguracji połączenia:

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

Obiekt pamięci podręcznej

Możesz także użyć fabryki pamięci podręcznej:

var cache = $cacheFactory('myCache');

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

Możesz go zaimplementować samodzielnie za pomocą $ cacheFactory (szczególnie ręcznie, gdy używasz $ resource):

var cache = $cacheFactory('myCache');

var data = cache.get(someKey);

if (!data) {
   $http.get(url).success(function(result) {
      data = result;
      cache.put(someKey, data);
   });
}
asgoth
źródło
47
Pytanie: jaki jest sens zapisywania danych w pamięci podręcznej w $ cacheFactory .. dlaczego nie po prostu zapisać ich w lokalnym obiekcie w usłudze? Jakieś dobre powody?
Spock
7
Sprawdź to. Daje wiele możliwości dostosowywania, w tym wsparcie localStorage, wsparcie
przekroczenia
4
Jestem szczególnie ciekawy kodu statusu 304 - czy pamięć podręczna przeglądarki działa bez włączania pamięci podręcznej: prawda? Jeśli nie, czy pamięć podręczna: prawda sprawia, że ​​działa? Czy buforowanie jest trwałe, czy tylko w pamięci RAM i jest zwalniane po zamknięciu strony?
sasha.sochka
3
Czy jest jakiś sposób na określenie limitu czasu dla tej pamięci podręcznej bez jej ręcznego wdrożenia?
Mark
11
@Spock, sama $ cacheFactory jest usługą, z której można korzystać na wielu kontrolerach i komponentach kątowych. Może być używany jako ogólna usługa interfejsu API do buforowania wszystkich $ http do pojedynczego obiektu obj, zamiast posiadania różnych obiektów usług dla każdego z nich.
Nirav Gandhi
48

Myślę, że jest teraz jeszcze łatwiejszy sposób. Umożliwia to podstawowe buforowanie dla wszystkich żądań $ http (które dziedziczy $ zasób):

 var app = angular.module('myApp',[])
      .config(['$httpProvider', function ($httpProvider) {
            // enable http caching
           $httpProvider.defaults.cache = true;
      }])
gspatel
źródło
46
Prawie nie chcesz buforować każdego pojedynczego żądania HTTP. Nie wiem, kiedy to się kiedykolwiek stanie?
Spock
1
Każda aplikacja / moduł jest inny, nie ?!
rodrigo-silveira
13
Jeśli chcesz buforować większość żądań, przydatne jest ustawienie wartości domyślnej na true.
Adrian Lynch
12

Łatwiejszy sposób na zrobienie tego w obecnej stabilnej wersji (1.0.6) wymaga znacznie mniej kodu.

Po skonfigurowaniu modułu dodaj fabrykę:

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

Teraz możesz przekazać to do kontrolera:

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

Jednym minusem jest to, że nazwy kluczy są również konfigurowane automatycznie, co może utrudnić ich wyczyszczenie. Mam nadzieję, że w jakiś sposób dodadzą nazwy kluczy.

James Skemp
źródło
7

Sprawdź bibliotekę kątową pamięci podręcznej jeśli lubisz wbudowane buforowanie $ http, ale chcesz mieć większą kontrolę. Można go użyć do płynnego rozszerzenia pamięci podręcznej $ http o czas życia, okresowe czyszczenie oraz opcję przechowywania pamięci podręcznej w localStorage, aby była dostępna między sesjami.

FWIW, zapewnia również narzędzia i wzorce do przekształcania pamięci podręcznej w bardziej dynamiczny rodzaj magazynu danych, z którym można wchodzić w interakcje jako POJO, a nie tylko jako domyślne ciągi JSON. Nie mogę jeszcze skomentować użyteczności tej opcji.

(Poza tym powiązane dane kątowe z biblioteki są swego rodzaju zamiennikiem zasobu $ i / lub Restangular i zależą od pamięci podręcznej kątowej.)

XML
źródło
3
Pamiętaj, że angular-datateraz jest przestarzałe. Najnowszy to js-data-angular js-data.io/v1.8.0/docs/js-data-angular
demisx
Biblioteka pamięci podręcznej kątowej ma funkcje, które powinny były zostać wbudowane w $ cacheFactory Angulara. Wbudowane rozwiązanie wydaje się prawie bezużyteczne, biorąc pod uwagę jego ograniczenia w możliwości wygaśnięcia określonych pamięci podręcznych. Fabryka pamięci podręcznej kątowej była również jedną z najłatwiejszych do wdrożenia bibliotek stron trzecich.
Darryl,
5

Ponieważ fabryki AngularJS są singletonami , możesz po prostu zapisać wynik żądania HTTP i odzyskać go przy następnym wstrzyknięciu usługi.

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;
      }
    };
  }
);
Rimian
źródło
Mam jedno pytanie, jak sprawdzić, czy GET się nie powiodło, a w takim przypadku nie umieszczać w pamięci podręcznej zasobu $ ... query ()
Robert
@robert możesz sprawdzić drugi argument metody .then lub jeszcze lepiej, użyj wywołania zwrotnego .catch. Na przykład $ http .get (url) .then (successCallback, failCallback) lub $ http .get (url) .then (successCallback, failCallback) .catch (errorCallback) Wywołanie błędu zostanie wykonane, nawet jeśli coś złego wydarzy się w failCallback , chociaż bardziej powszechne jest w ogóle unikanie oddzwaniania po awarii i używanie .then (sukces) .catch (manageRequestFail). Mam nadzieję, że to pomoże zrozumieć pomysł, więcej informacji w kanciastej dokumentacji $ 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}
        });
    }]);

ustaw pamięć podręczną na wartość true.

Howardyan
źródło
Byłoby to tak bezpieczne, jak aplikacja kliencka korzystająca z samej przeglądarki, tak jak każda inna aplikacja internetowa.
bhantol,
-1

W Angular 8 możemy to zrobić w następujący sposób:

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

Możesz to tak nazwać:

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


});

Powyższy kod będzie buforował wynik zdalnego interfejsu API przy pierwszym wywołaniu, dzięki czemu będzie można go użyć przy kolejnych żądaniach do tej metody.

Raghav
źródło