Development Tip

angular2 http 서비스로 결과 캐싱

yourdevel 2020. 11. 17. 21:11
반응형

angular2 http 서비스로 결과 캐싱


서비스를 통해 HTTP GET 요청을 노출하고 여러 구성 요소가이 데이터 (사용자 프로필 세부 정보)를 사용하고 있습니다. 첫 번째 구성 요소 요청이 실제로 서버에 대한 HTTP GET 요청을 수행하고 결과를 캐시하여 결과 요청이 서버를 다시 호출하는 대신 캐시 된 데이터를 사용하도록하고 싶습니다.

다음은 서비스에 대한 예입니다. Angular2 및 typescript로이 캐시 계층을 구현하는 것이 좋습니다.

import {Inject, Injectable} from 'angular2/core';
import {Http, Headers} from "angular2/http";
import {JsonHeaders} from "./BaseHeaders";
import {ProfileDetails} from "../models/profileDetails";

@Injectable()
export class ProfileService{
    myProfileDetails: ProfileDetails = null;

    constructor(private http:Http) {

    }

    getUserProfile(userId:number) {
        return this.http.get('/users/' + userId + '/profile/', {
                headers: headers
            })
            .map(response =>  {
                if(response.status==400) {
                    return "FAILURE";
                } else if(response.status == 200) {
                    this.myProfileDetails = new ProfileDetails(response.json());
                    return this.myProfileDetails;
                }
            });
    }
}

마지막 댓글과 관련하여 제가 생각할 수있는 가장 쉬운 방법은 다음과 같습니다. 하나의 속성이 있고 해당 속성이 요청을 보유 할 서비스를 만듭니다.

class Service {
  _data;
  get data() {
    return this._data;
  }
  set data(value) {
    this._data = value;
  }
}

저것과 같이 쉬운. plnkr의 다른 모든 것은 변경되지 않습니다. 자동으로 인스턴스화되기 때문에 서비스에서 요청을 제거했습니다 (우리는 new Service...생성자를 통해 매개 변수를 전달하는 쉬운 방법을 알지 못합니다).

이제 서비스가 생겼습니다. 이제 컴포넌트에서 요청을 작성하고이를 Service 변수에 할당합니다. data

class App {
  constructor(http: Http, svc: Service) {

    // Some dynamic id
    let someDynamicId = 2;

    // Use the dynamic id in the request
    svc.data = http.get('http://someUrl/someId/'+someDynamicId).share();

    // Subscribe to the result
    svc.data.subscribe((result) => {
      /* Do something with the result */
    });
  }
}

서비스 인스턴스는 모든 구성 요소에 대해 동일하므로 값을 할당하면 data모든 구성 요소에 반영됩니다.

다음 은 작업 예제 가있는 plnkr 입니다.

참고


주 () 연산자는 모든 구독이 제공됩니다 첫 번째 요청에 작동하고 당신은 그렇지 않은 작업, 또 다른 요청을 만들 것, 또 다른 하나를 만들 수 있습니다. (이 경우는 angular2 SPA의 경우 항상 구성 요소를 생성 / 파괴하므로 매우 일반적입니다)

ReplaySubject사용 하여 http Observable 의 값을 저장했습니다 . ReplaySubject의 관찰은 가입자에게 이전 값을 제공 할 수 있습니다.

서비스:

@Injectable()
export class DataService {
    private dataObs$ = new ReplaySubject(1);

    constructor(private http: HttpClient) { }

    getData(forceRefresh?: boolean) {
        // If the Subject was NOT subscribed before OR if forceRefresh is requested 
        if (!this.dataObs$.observers.length || forceRefresh) {
            this.http.get('http://jsonplaceholder.typicode.com/posts/2').subscribe(
                data => this.dataObs$.next(data),
                error => {
                    this.dataObs$.error(error);
                    // Recreate the Observable as after Error we cannot emit data anymore
                    this.dataObs$ = new ReplaySubject(1);
                }
            );
        }

        return this.dataObs$;
    }
}

구성 요소 :

@Component({
  selector: 'my-app',
  template: `<div (click)="getData()">getData from AppComponent</div>`
})
export class AppComponent {
    constructor(private dataService: DataService) {}

getData() {
    this.dataService.getData().subscribe(
        requestData => {
            console.log('ChildComponent', requestData);
        },
        // handle the error, otherwise will break the Observable
        error => console.log(error)
    );
}
    }
}

완전히 작동하는 PLUNKER
(콘솔 및 네트워크 탭 확인)


userId취급을 생략했습니다 . 대신 data배열 및 배열 observable(요청 된 각에 대해 하나씩 userId) 을 관리해야합니다 .

import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/observable/of';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import {Data} from './data';

@Injectable()
export class DataService {
  private url:string = 'https://cors-test.appspot.com/test';

  private data: Data;
  private observable: Observable<any>;

  constructor(private http:Http) {}

  getData() {
    if(this.data) {
      // if `data` is available just return it as `Observable`
      return Observable.of(this.data); 
    } else if(this.observable) {
      // if `this.observable` is set then the request is in progress
      // return the `Observable` for the ongoing request
      return this.observable;
    } else {
      // example header (not necessary)
      let headers = new Headers();
      headers.append('Content-Type', 'application/json');
      // create the request, store the `Observable` for subsequent subscribers
      this.observable = this.http.get(this.url, {
        headers: headers
      })
      .map(response =>  {
        // when the cached data is available we don't need the `Observable` reference anymore
        this.observable = null;

        if(response.status == 400) {
          return "FAILURE";
        } else if(response.status == 200) {
          this.data = new Data(response.json());
          return this.data;
        }
        // make it shared so more than one subscriber can get the result
      })
      .share();
      return this.observable;
    }
  }
}

플 런커 예

You can find another interesting solution at https://stackoverflow.com/a/36296015/217408

참고URL : https://stackoverflow.com/questions/34104277/caching-results-with-angular2-http-service

반응형