【问题标题】:Preserve the order of the http calls in angular以角度保留 http 调用的顺序
【发布时间】:2018-08-28 21:03:24
【问题描述】:

我正在尝试使用我在SO 上找到的几种方法来解决我面临的订单问题,但均未成功。

我有一个方法,我正在为 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数组?

【问题讨论】:

  • 只是出于好奇..您是否有理由在单个请求中不将所有 id 作为数组发送并得到一个数组作为响应?
  • 这就是我们提供服务的方式。它一次可以处理一层。

标签: angular rxjs angular-httpclient


【解决方案1】:

由于 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));
    })
}

【讨论】:

  • 完美,它正在工作!谢谢!在forEach 中你有一个错误。应该是:res.forEach(dimension =&gt; this.displayNewTileLayer(dimension));
  • @Gabriel 感谢您的评论,很高兴它成功了。我修正了我的错误。
【解决方案2】:

我会考虑使用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 相同。您应该考虑是否可以将排序逻辑移至服务器,即有一个服务接收一组 id (selectedTileLayersIds) 并返回和维度数组。通过这种方式,您可以减少网络流量并避免一系列顺序同步的 http 调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 2018-01-25
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    相关资源
    最近更新 更多