目前我的应用程序有一个数据服务,它向服务器发出http请求以获取数据。每个组件都会单独调用此服务以获取所需的数据。
public getHospitals() {
return this._http.get(this.baseUrl + "/hospitals/")
.map(res => res.json())
.map(json => automapper.map(typeof (JSON), Hospital, json));
}
public getClinics() {
return this._http.get(this.baseUrl + "/clinics/")
.map(res => res.json())
.map(json => automapper.map(typeof (JSON), Clinic, json));
}
当我加载示例页面时,我有一个Hospital组件和一个Clinic组件。这两个组件调用数据服务中的相应方法。
我最近扩展了服务器以允许单个请求,该请求指定了所需的数据。下面是一个如何调用它的例子。
public getLocalData(body) {
const headers = new Headers({ "Content-Type": "application/json" });
const options = new RequestOptions({ headers });
return this._http.post(this.baseUrl, JSON.stringify(body), options)
.map(res => res.json());
}
public getHospitals() {
return this.getLocalData(["Hospitals"])
.map(json => automapper.map(typeof (JSON), Hospital, json.Hospitals));
}
public getClinics() {
return this.getLocalData(["Clinics"])
.map(json => automapper.map(typeof (JSON), Clinic, json.Clinics));
}
可以这样调用,这将返回所有数据:const localData = this.getLocalData(["Hospitals", "Clinics"]);
我的问题是,如何修改这两个组件以构建getLocalData
方法的body参数,并只生成一个http请求?
编辑:我也希望对此进行扩展,以便最终我可以说10个以上的组件,每个组件都有自己的本地数据集来请求。
答案 0 :(得分:1)
可能你想要实现这样的东西:
@Injectable()
export class LocalDataService {
private getLocalData(body) {
const headers = new Headers({ "Content-Type": "application/json" });
const options = new RequestOptions({ headers });
return this._http.post(this.baseUrl, JSON.stringify(body), options)
.map(res => res.json());
}
public getHospitals() {
if (!this.pendingRequest) {
this.pendingRequest = this.getLocalData(["Hospitals", "Clinics"]);
this.cleanUpSubscription = this.pendingRequest.subscribe(() => this.cleanUp(), () => this.cleanUp());
}
return this.pendingRequest.map(json => automapper.map(typeof (JSON), Hospital, json.Hospitals));
}
public getClinics() {
if (!this.pendingRequest) {
this.pendingRequest = this.getLocalData(["Hospitals", "Clinics"]);
this.cleanUpSubscription = this.pendingRequest.subscribe(() => this.cleanUp(), () => this.cleanUp());
}
return this.pendingRequest.map(json => automapper.map(typeof (JSON), Clinic, json.Clinics));
}
private cleanUp() {
if (this.cleanUpSubscription) {
this.cleanUpSubscription.unsubscribe();
this.cleanUpSubscription = null;
}
this.pendingRequest = null;
}
private pendingRequest: Observable<Response> = null;
private cleanUpSubscription: Subscription = null;
}
我已缓存observable以便返回if后续请求。因此,如果我们有一个正在进行的请求(让我们说医院),并要求诊所的API,直到医院还没有退回,我们将不会提出额外的请求。将返回现有的observable并且两个组件(Hospitals and Clinics)都可以单独处理响应。
此外,我还添加了一些cleanUp代码,以便在请求完成后删除缓存的Observable。后续请求将再次命中API。
注意:我尚未测试此代码,因此可能需要进行一些其他更改。
答案 1 :(得分:1)
调用服务获取数据后,您可以等到所有ngZone
微任务完成(其中包括可能对服务做出的任何其他请求),然后触发单个{{1}请求。您需要修改http
方法以返回getLocalData
rxjs
,一旦数据从服务器返回,您就可以在主题上发布数据,以便将它们传递回适当的呼叫者。
免责声明 我不完全确定这是否是解决此问题的最佳方式,但上述情况应该有效。
以下是修改后的服务和Subject
方法。
getLocalData
}
我不知道如何重写它,以便各个服务方法可以请求多个数据集,如问题中所示,但我确信有一种方法可以使用import {Observable} from "rxjs/Observable";
import "rxjs/add/operator/map";
import "rxjs/add/operator/first";
import {Subject} from "rxjs/Subject";
// ...
public getHospitals() {
return this.getLocalData("Hospitals")
.map(json => automapper.map(typeof (JSON), Hospital, json.Hospitals));
}
public getClinics() {
return this.getLocalData("Clinics")
.map(json => automapper.map(typeof (JSON), Clinic, json.Clinics));
}
private requests = {};
private isAggregating = false;
private getLocalData(dataKey): Subject {
this.requests[dataKey] = this.requests[dataKey] || new Subject();
if(!this.isAggregating){
this.isAggregating = true;
this.ngZone.onMicrotaskEmpty.first().subscribe(() => {
var requests = this.requests;
this.requests = {};
this.isAggregating = false;
const headers = new Headers({ "Content-Type": "application/json" });
const options = new RequestOptions({ headers });
this._http.post(this.baseUrl, JSON.stringify(Object.keys(requests)), options)
.map(res => {
return res.json();
}).subscribe((data) => {
Object.keys(data)
.filter((key) => requests[key])
.forEach((key)=>{
requests[key].next(data[key]);
requests[key].complete();
});
});
});
}
return this.requests[dataKey];
地图进行创建以启用请求多个集合而不是单个集合。