แคชการตอบสนองบริการ HTTP 'รับ' ใน AngularJS หรือไม่


211

ฉันต้องการที่จะสามารถสร้างบริการ AngularJS ที่กำหนดเองที่ทำให้การร้องขอ HTTP 'รับ' เมื่อวัตถุข้อมูลของมันว่างเปล่าและเติมวัตถุข้อมูลในความสำเร็จ

ครั้งต่อไปที่มีการโทรไปยังบริการนี้ฉันต้องการข้ามค่าใช้จ่ายในการร้องขอ HTTP อีกครั้งและส่งคืนวัตถุข้อมูลที่แคช

เป็นไปได้ไหม

คำตอบ:


315

$ httpของ Angular มีแคชในตัว ตามเอกสาร:

cache - {boolean | Object} - ค่าบูลีนหรือวัตถุที่สร้างด้วย $ cacheFactory เพื่อเปิดใช้งานหรือปิดใช้งานการแคชการตอบสนอง HTTP ดู $ http แคชสำหรับข้อมูลเพิ่มเติม

ค่าบูลีน

เพื่อให้คุณสามารถตั้งค่าcacheเพื่อความจริงในตัวเลือก:

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

หรือถ้าคุณชอบประเภทการโทร:

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

วัตถุแคช

คุณยังสามารถใช้โรงงานแคช:

var cache = $cacheFactory('myCache');

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

คุณสามารถนำไปใช้ด้วยตัวเองโดยใช้$ cacheFactory (โดยเฉพาะอย่างยิ่งเมื่อใช้ทรัพยากร $):

var cache = $cacheFactory('myCache');

var data = cache.get(someKey);

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

47
คำถาม: อะไรคือจุดของการบันทึกข้อมูลที่แคชไว้ใน $ cacheFactory .. ทำไมไม่เพียงบันทึกลงในวัตถุในเครื่องในบริการ มีเหตุผลที่ดีไหม?
สป็อค

7
ลองดู. มันช่วยให้คุณปรับแต่งมากมายรวมถึงการสนับสนุน localStorage การสนับสนุนการหมดเวลาสารพัดทุกชนิดhttp://jmdobry.github.io/angular-cache/
Erik Donohoo

4
ฉันอยากรู้เกี่ยวกับรหัสสถานะ 304 - เบราว์เซอร์แคชทำงานโดยไม่เปิดใช้งานแคช: จริงหรือไม่ ถ้าไม่แคชไม่จริงทำงานได้หรือไม่ แคชถาวรหรือเป็นเพียง RAM และไม่โหลดเมื่อปิดหน้าเว็บหรือไม่
sasha.sochka

3
วิธีใดที่จะระบุการ จำกัด เวลาในแคชนี้โดยไม่ต้องใช้งานด้วยตนเอง
Mark

11
@Spock, $ cacheFactory เป็นบริการที่สามารถใช้ได้กับคอนโทรลเลอร์หลายตัวและส่วนประกอบเชิงมุม มันสามารถใช้เป็นบริการ api ทั่วไปเพื่อแคช $ http ของคุณทั้งหมดลงในบริการ obj เดียวแทนที่จะมีวัตถุบริการที่แตกต่างกันสำหรับแต่ละคน
Nirav Gandhi

48

ฉันคิดว่ามันมีวิธีที่ง่ายกว่านี้อีกแล้ว สิ่งนี้ทำให้การแคชพื้นฐานสำหรับคำขอ $ http ทั้งหมด (ซึ่ง $ resource สืบทอด):

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

46
คุณแทบจะไม่ต้องการแคชทุกคำขอ HTTP เดียว ฉันไม่เห็นว่าจะเป็นอย่างนั้นเมื่อไหร่?
สป็อค

1
ทุกแอพพลิเคชั่น / โมดูลต่างกันใช่มั้ย!
rodrigo-silveira

13
หากคุณต้องการแคชคำขอส่วนใหญ่แล้วการตั้งค่าเริ่มต้นเป็นจริงจะมีประโยชน์
Adrian Lynch

12

วิธีที่ง่ายกว่าในการทำเช่นนี้ในเวอร์ชั่นเสถียรปัจจุบัน (1.0.6) ต้องใช้รหัสน้อยกว่ามาก

หลังจากติดตั้งโมดูลแล้วเพิ่มโรงงาน:

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

ตอนนี้คุณสามารถส่งสิ่งนี้ไปยังคอนโทรลเลอร์ของคุณได้:

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

ข้อเสียอย่างหนึ่งคือชื่อคีย์นั้นตั้งค่าโดยอัตโนมัติเช่นกัน หวังว่าพวกเขาจะเพิ่มวิธีรับชื่อคีย์


7

ลองใช้ไลบรารีangular-cacheถ้าคุณชอบการแคชในตัวของ $ http แต่ต้องการการควบคุมที่มากกว่า คุณสามารถใช้เพื่อเพิ่มแคช $ http ได้อย่างราบรื่นด้วยการล้างข้อมูลตามระยะเวลาการล้างข้อมูลเป็นระยะและตัวเลือกในการคงแคชไว้ใน localStorage เพื่อให้สามารถใช้งานได้ในเซสชันต่างๆ

FWIW มันยังมีเครื่องมือและรูปแบบสำหรับทำให้แคชของคุณเป็นแหล่งข้อมูลที่มีพลวัตมากขึ้นซึ่งคุณสามารถโต้ตอบกับในฐานะ POJO แทนที่จะเป็นแค่สตริง JSON เริ่มต้น ยังไม่สามารถแสดงความคิดเห็นเกี่ยวกับยูทิลิตี้ของตัวเลือกดังกล่าวได้

(จากนั้นยิ่งไปกว่านั้นangular-dataไลบรารี่ที่เกี่ยวข้องคือการแทนที่ของ $ resource และ / หรือ Restangular และขึ้นอยู่กับ angular-cache)


3
โปรดทราบว่าangular-dataเลิกใช้แล้วในขณะนี้ ล่าสุดคือjs-data-angular js-data.io/v1.8.0/docs/js-data-angular
demisx

ไลบรารีเชิงมุมแคชมีคุณลักษณะที่ควรสร้างไว้ใน $ cacheFactory ของ Angular โซลูชันในตัวดูเหมือนไร้ประโยชน์เกือบจะเนื่องจากข้อ จำกัด ในการหมดอายุแคชเฉพาะ โรงงานแคชเชิงมุมเป็นหนึ่งในห้องสมุดบุคคลที่สามที่ง่ายที่สุดที่จะใช้เช่นกัน
Darryl

5

เนื่องจากโรงงานของ AngularJS เป็นซิงเกิลคุณสามารถจัดเก็บผลลัพธ์ของคำขอ http และดึงข้อมูลในครั้งถัดไปที่บริการของคุณถูกฉีดเข้าไปในบางสิ่ง

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

ฉันมีหนึ่งคำถามว่าจะตรวจสอบได้อย่างไรว่า GET ล้มเหลวและในกรณีนั้นไม่ควรใส่ไว้ในแคชของ $ resource ... query ()
robert

@robert คุณสามารถตรวจสอบอาร์กิวเมนต์ที่สองของวิธีการ. then หรือดีกว่านั้นให้ใช้. call call ตัวอย่างเช่น $ http .get (url) .then (successCallback, failCallback) หรือ $ http .get (url) .then (successCallback, FailCallback) .catch (errorCallback) การเรียกกลับข้อผิดพลาดจะถูกดำเนินการแม้ว่าจะมีบางสิ่งที่ไม่ดีเกิดขึ้นใน failCallback แม้ว่าจะเป็นเรื่องปกติมากขึ้นในการหลีกเลี่ยงการเรียกกลับที่ล้มเหลวและใช้. แล้ว (สำเร็จ) .catch (ManageRequestFail) หวังว่าจะช่วยให้เข้าใจความคิดข้อมูลเพิ่มเติมในเอกสาร $ 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}
        });
    }]);

ตั้งค่าแคชให้เป็นจริง


นี่จะปลอดภัยเท่ากับแอปพลิเคชันไคลเอนต์ที่มีเบราว์เซอร์เหมือนกับแอปพลิเคชันเว็บอื่น ๆ
bhantol

-1

ในเชิงมุม 8 เราสามารถทำสิ่งนี้:

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

คุณสามารถโทรแบบนี้:

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


});

โค้ดด้านบนจะแคชผลลัพธ์ของ API ระยะไกลในการโทรครั้งแรกเพื่อให้สามารถใช้กับการร้องขอเพิ่มเติมไปยังวิธีการนั้นได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.