保留 angular 中的 http 调用顺序
Preserve the order of the http calls in angular
我正在尝试使用我在 上找到的几种方法解决我面临的顺序问题,但没有成功。
我有一个方法,我正在为 leaflet 层的数组加载一些数据:
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id)
.subscribe(
dimensions => this.displayNewTileLayer(dimensions)
);
}
);
}
然后我有一个方法,其中发生 http
调用:
public getTileLayerDimensions(urlToFormat: string, tileLayerName: string, tileLayerId: string): Observable<Dimensions> {
const capabilitiesUrl = `serviceUrl`;
return this.httpClient.get(capabilitiesUrl, {responseType: "text"})
.map(res => {
// Doing stuff with data
return dataForLayer;
});
}
问题是,displayNewTileLayer(dimensions)
方法的调用顺序是随机的。有没有办法保留项目存储的顺序
selectedTileLayerIds
数组?
由于 http-calls 是异步的,响应可能 而不是 以与发出请求相同的顺序到达。您可以做的是创建一个请求列表,创建一个 forkJoin 并等待所有响应得到解决。然后,您可以为所有响应调用 displayNewTileLayer(dimensions)
方法。
这是一个例子
const httpCalls = []; // store the requests here
for (let i = 0; i < 3; i++) {
httpCalls.push(this.http.get('someUrl').map(response => response));
}
forkJoin(httpCalls).subscribe(res => {
// all responses completed. returns an array of data (one for each response).
console.log('res', res);
});
在您的情况下,此代码可能有效:(代码未经测试,您可能必须在代码中导入 forkJoin 运算符)
import { forkJoin } from 'rxjs/observable/forkJoin';
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
let requests = []:
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
const request = this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id)
requests.push(request);
}
);
forkJoin(requests).subscribe(res => {
res.forEach(dimension => this.displayNewTileLayer(dimension));
})
}
我会考虑使用 concat
运算符。
您的代码如下所示
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
let concatObs;
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
const httpCall = this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id);
if (!concatObs) {
concatObs = httpCall);
} else {
concatObs.concat(httpCall);
}
}
);
concatObs.subscribe(
dimensions => this.displayNewTileLayer(dimensions)
);
}
这样 concatObs 的发射顺序与数组 selectedTileLayersIds
相同。您应该考虑是否有可能将排序逻辑移动到服务器,即有一个服务接收 ids (selectedTileLayersIds
) 和 returns 数组以及维度数组。通过这种方式,您可以减少网络流量并避免一系列顺序同步 http 调用。
我正在尝试使用我在
我有一个方法,我正在为 leaflet 层的数组加载一些数据:
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id)
.subscribe(
dimensions => this.displayNewTileLayer(dimensions)
);
}
);
}
然后我有一个方法,其中发生 http
调用:
public getTileLayerDimensions(urlToFormat: string, tileLayerName: string, tileLayerId: string): Observable<Dimensions> {
const capabilitiesUrl = `serviceUrl`;
return this.httpClient.get(capabilitiesUrl, {responseType: "text"})
.map(res => {
// Doing stuff with data
return dataForLayer;
});
}
问题是,displayNewTileLayer(dimensions)
方法的调用顺序是随机的。有没有办法保留项目存储的顺序
selectedTileLayerIds
数组?
由于 http-calls 是异步的,响应可能 而不是 以与发出请求相同的顺序到达。您可以做的是创建一个请求列表,创建一个 forkJoin 并等待所有响应得到解决。然后,您可以为所有响应调用 displayNewTileLayer(dimensions)
方法。
这是一个例子
const httpCalls = []; // store the requests here
for (let i = 0; i < 3; i++) {
httpCalls.push(this.http.get('someUrl').map(response => response));
}
forkJoin(httpCalls).subscribe(res => {
// all responses completed. returns an array of data (one for each response).
console.log('res', res);
});
在您的情况下,此代码可能有效:(代码未经测试,您可能必须在代码中导入 forkJoin 运算符)
import { forkJoin } from 'rxjs/observable/forkJoin';
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
let requests = []:
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
const request = this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id)
requests.push(request);
}
);
forkJoin(requests).subscribe(res => {
res.forEach(dimension => this.displayNewTileLayer(dimension));
})
}
我会考虑使用 concat
运算符。
您的代码如下所示
private loadSelectedTileLayersCapabilities(): void {
let tempTileLayer;
let concatObs;
this.selectedTileLayerIds.forEach(
(selectedTileLayer: string) => {
tempTileLayer = this.getTileLayerById(selectedTileLayer);
const httpCall = this.capabilitiesService.getTileLayerDimensions(tempTileLayer.url, tempTileLayer.name, tempTileLayer.id);
if (!concatObs) {
concatObs = httpCall);
} else {
concatObs.concat(httpCall);
}
}
);
concatObs.subscribe(
dimensions => this.displayNewTileLayer(dimensions)
);
}
这样 concatObs 的发射顺序与数组 selectedTileLayersIds
相同。您应该考虑是否有可能将排序逻辑移动到服务器,即有一个服务接收 ids (selectedTileLayersIds
) 和 returns 数组以及维度数组。通过这种方式,您可以减少网络流量并避免一系列顺序同步 http 调用。