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;
}
});
}
}
공유() 연산자는 첫 번째 요청에 대해서만 작업을 수행하며, 모든 구독이 제공되고 다른 구독을 생성하면 해당 구독이 작동하지 않고 다른 요청이 수행됩니다.(이 경우는 매우 흔하며, 항상 생성/파괴하는 Angular2 SPA의 경우)
저는 ReplaySubject를 사용하여 http 관찰 가능한 값을 저장했습니다.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)
);
}
}
}
완전히 작동하는 플런커
(콘솔 및 네트워크 탭 관찰)
나는 생략했습니다.userId
처리.이를 위해서는 다음과 같은 스토리지 시스템을 관리가 필요합니다.data
그리고 일련의observable
(요청된 각 1개당 1개)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;
}
}
}
https://stackoverflow.com/a/36296015/217408 에서 또 다른 흥미로운 솔루션을 찾을 수 있습니다.
당신의 마지막 의견과 관련하여, 이것이 제가 생각할 수 있는 가장 쉬운 방법입니다: 하나의 속성을 가지고 해당 속성이 요청을 유지할 서비스를 만드십시오.
class Service {
_data;
get data() {
return this._data;
}
set data(value) {
this._data = value;
}
}
그것처럼 간단해.plnkr에 있는 다른 모든 것들은 손대지 않을 것입니다.요청이 자동으로 인스턴스화되므로 서비스에서 요청을 제거했습니다(그렇지 않음).new 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 */
});
}
}
NAT 서비스 인스턴스는 모든 구성 요소에 대해 동일하므로 다음에 값을 할당할 때data
모든 구성 요소에 반영됩니다.
여기 실용적인 예가 있는 plnkr가 있습니다.
언급
언급URL : https://stackoverflow.com/questions/34104277/caching-results-with-angular2-http-service
'programing' 카테고리의 다른 글
관찰 가능한 오류를 수동으로 발생시키는 방법은 무엇입니까? (0) | 2023.09.05 |
---|---|
코드를 사용하여 버튼 클릭을 시뮬레이션하는 방법은 무엇입니까? (0) | 2023.09.05 |
MariaDB 마스터에서 마스터로의 복제 자동 증분이 순차적이지 않음 (0) | 2023.09.05 |
데이터베이스의 결과 페이지화는 어떻게 작동합니까? (0) | 2023.09.05 |
두 CG 지점 사이의 거리를 찾는 방법은 무엇입니까? (0) | 2023.09.05 |