ค้นหาเว็บไซต์

Angular - วิธีที่ดีที่สุดในการเก็บแคชการตอบสนอง HTTP


ฉันมีบริการหลายอย่างที่มีคำขอไปยังบริการ REST และฉันต้องการแคชข้อมูลที่ได้รับจากเซิร์ฟเวอร์เพื่อนำไปใช้ต่อ ใครสามารถบอกได้ไหมว่าวิธีที่ดีที่สุดในการแคชการตอบสนองคืออะไร?

คำตอบ #1

คุณจะพบคำตอบหลายข้อที่นี่: Angular 2 แคชผลลัพธ์ข้อมูล observable http

ฉันขอแนะนำให้สร้างคลาสง่ายๆ ชื่อ Cacheable<> ที่ช่วยจัดการแคชของข้อมูลที่ดึงมาจากเซิร์ฟเวอร์ HTTP หรือแหล่งอื่นๆ

declare type GetDataHandler<T> = () => Observable<T>;

export class Cacheable<T> {

    protected data: T;
    protected subjectData: Subject<T>;
    protected observableData: Observable<T>;
    public getHandler: GetDataHandler<T>;

    constructor() {
      this.subjectData = new ReplaySubject(1);
      this.observableData = this.subjectData.asObservable();
    }

    public getData(): Observable<T> {
      if (!this.getHandler) {
        throw new Error("getHandler is not defined");
      }
      if (!this.data) {
        this.getHandler().map((r: T) => {
          this.data = r;
          return r;
        }).subscribe(
          result => this.subjectData.next(result),
          err => this.subjectData.error(err)
        );
      }
      return this.observableData;
    }

    public resetCache(): void {
      this.data = null;
    }

    public refresh(): void {
      this.resetCache();
      this.getData();
    }

}

การใช้งาน

ประกาศอ็อบเจ็กต์ Cacheable<> (โดยสมมติว่าเป็นส่วนหนึ่งของบริการ):

list: Cacheable<string> = new Cacheable<string>();

และผู้ดูแล:

this.list.getHandler = () => {
// get data from server
return this.http.get(url)
.map((r: Response) => r.json() as string[]);
}

การโทรจากคอมโพเนนต์:

//gets data from server
List.getData().subscribe(…)

รายละเอียดเพิ่มเติมและตัวอย่างโค้ดอยู่ที่นี่: http://devinstance.net/articles/20171021/rxjs-cacheable

คำตอบ #2

วิธีที่ง่ายที่สุดในการเก็บข้อมูลในบริการคือการใช้ shareReplay()

example.service.ts

import { shareReplay } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({providedIn: 'root'})
export class ExampleService {

    private readonly _data: Observable<IExampleModel[]>;

    constructor(private readonly http: HttpClient) {
        this._data = 
            this.http.get<IExampleModel[]>('/api/example-entities/')
                .pipe(shareReplay());
        }
        
    getExampleEntities() : Observable<IExampleModel[]> {
        return this._data;
    }
}

แนวทางทางเลือกที่ใช้อย่างแพร่หลายกับ ReplaySubject<T>(1) สามารถพบได้ที่นี่

บทความที่เกี่ยวข้อง