Tembolok respons layanan 'Dapatkan' HTTP di AngularJS?

211

Saya ingin dapat membuat layanan AngularJS kustom yang membuat permintaan 'Dapatkan' HTTP ketika objek datanya kosong dan mengisi objek data pada kesuksesan.

Lain kali panggilan dibuat untuk layanan ini, saya ingin memotong overhead membuat permintaan HTTP lagi dan bukannya mengembalikan objek data yang di-cache.

Apakah ini mungkin?

Gavriguy
sumber

Jawaban:

315

$ Http Angular memiliki cache bawaan . Menurut dokumen:

cache - {boolean | Object} - Nilai boolean atau objek yang dibuat dengan $ cacheFactory untuk mengaktifkan atau menonaktifkan caching dari respons HTTP. Lihat $ http Caching untuk informasi lebih lanjut .

Nilai Boolean

Sehingga Anda dapat mengatur cacheuntuk benar dalam pilihan nya:

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

atau, jika Anda lebih suka jenis panggilan konfigurasi:

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

Objek Cache

Anda juga dapat menggunakan pabrik cache:

var cache = $cacheFactory('myCache');

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

Anda dapat menerapkannya sendiri menggunakan $ cacheFactory (terutama dengan mudah saat menggunakan $ 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
sumber
47
Pertanyaan: apa gunanya menyimpan data yang di-cache ke $ cacheFactory .. mengapa tidak menyimpannya ke objek lokal di Layanan? Ada alasan bagus?
Spock
7
Lihat ini. Ini memberi Anda banyak kemampuan penyesuaian termasuk dukungan localStorage, dukungan timeout, semua jenis barang http://jmdobry.github.io/angular-cache/
Erik Donohoo
4
Saya terutama ingin tahu tentang kode status 304 - apakah cache browser berfungsi tanpa mengaktifkan cache: true? Jika tidak, apakah cache: true membuatnya berfungsi? Apakah caching permanen atau hanya dalam RAM dan diturunkan saat halaman ditutup?
sasha.sochka
3
Adakah cara untuk menentukan batas waktu pada cache ini tanpa menerapkannya secara manual?
Markus
11
@Spock, $ cacheFactory sendiri adalah layanan yang dapat digunakan di banyak pengontrol dan komponen bersudut. Ini dapat digunakan sebagai layanan api umum untuk men-cache semua $ http Anda ke dalam satu objek layanan daripada memiliki objek layanan yang berbeda untuk masing-masing.
Nirav Gandhi
48

Saya pikir ada cara yang lebih mudah sekarang. Ini memungkinkan caching dasar untuk semua permintaan $ http (yang diwarisi $ resource):

 var app = angular.module('myApp',[])
      .config(['$httpProvider', function ($httpProvider) {
            // enable http caching
           $httpProvider.defaults.cache = true;
      }])
gspatel
sumber
46
Anda tidak ingin melakukan cache setiap permintaan http tunggal. Saya tidak melihat kapan itu akan terjadi?
Spock
1
Setiap aplikasi / modul berbeda, bukan ?!
rodrigo-silveira
13
Jika Anda ingin men-cache sebagian besar permintaan maka pengaturan default ke true berguna.
Adrian Lynch
12

Cara yang lebih mudah untuk melakukan ini dalam versi stabil saat ini (1.0.6) membutuhkan kode jauh lebih sedikit.

Setelah mengatur modul Anda tambahkan pabrik:

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

Sekarang Anda bisa meneruskan ini ke controller Anda:

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

Salah satu kelemahannya adalah bahwa nama-nama kunci juga diatur secara otomatis, yang dapat membuatnya sulit. Semoga mereka akan menambahkan cara untuk mendapatkan nama kunci.

James Skemp
sumber
7

Periksa cache cache sudut jika Anda suka caching bawaan $ http tetapi ingin lebih banyak kontrol. Anda dapat menggunakannya untuk menambah cache $ http secara mulus dengan pembersihan time-to-live, berkala, dan opsi mempertahankan cache ke localStorage sehingga tersedia di seluruh sesi.

FWIW, ia juga menyediakan alat dan pola untuk membuat cache Anda menjadi semacam penyimpanan data yang lebih dinamis yang dapat Anda berinteraksi dengan POJO, bukan hanya string JSON default. Belum dapat mengomentari utilitas opsi itu.

(Kemudian, di atas semua itu, data angular library terkait adalah semacam pengganti $ resource dan / atau Restangular, dan bergantung pada cache-angular.)

XML
sumber
3
Harap dicatat bahwa angular-datasudah usang sekarang. Yang terakhir adalah js-data-angular js-data.io/v1.8.0/docs/js-data-angular
demisx
Perpustakaan angular-cache memiliki fitur yang seharusnya dibangun ke $ cacheFactory Angular. Solusi built-in tampaknya hampir tidak berguna mengingat keterbatasannya untuk dapat kedaluwarsa cache tertentu. Pabrik cache angular adalah salah satu perpustakaan pihak ke-3 yang paling mudah untuk diimplementasikan juga.
Darryl
5

Karena pabrik AngularJS adalah lajang , Anda cukup menyimpan hasil permintaan http dan mengambilnya saat layanan Anda disuntikkan ke dalam sesuatu.

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
sumber
Saya punya satu pertanyaan bagaimana memeriksa apakah GET gagal dan dalam kasus itu tidak dimasukkan ke dalam cache $ resource ... query ()
robert
@robert Anda dapat memeriksa argumen kedua metode .then atau lebih baik lagi, gunakan panggilan balik .catch. Misalnya $ http .get (url) .then (successCallback, failCallback) atau $ http .get (url) .then (successCallback, failCallback) .catch (errorCallback) Callback kesalahan akan dieksekusi bahkan jika sesuatu yang buruk terjadi pada failCallback , meskipun itu lebih umum untuk menghindari panggilan balik yang gagal sama sekali dan menggunakan .then (sukses) .catch (manageRequestFail). Harapan yang membantu untuk memahami ide, info lebih lanjut di dokumentasi $ http sudut.
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}
        });
    }]);

setel cache menjadi true.

Howardyan
sumber
Ini akan seaman aplikasi klien dengan browser itu sendiri sama seperti aplikasi web lainnya.
bhantol
-1

Di Angular 8 kita bisa melakukan ini:

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

Anda bisa menyebutnya seperti ini:

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


});

Kode di atas akan men-cache hasil API jarak jauh saat panggilan pertama sehingga dapat digunakan pada permintaan lebih lanjut untuk metode itu.

Raghav
sumber