在继续操作之前,如何等待for循环内的订阅完成 [英] How to wait for subscriptions inside a for loop to complete before proceeding

查看:148
本文介绍了在继续操作之前,如何等待for循环内的订阅完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在for循环中有一个预订,该预订从外部源获取JSON数据作为一系列类别数据",然后根据用户的当前位置过滤该数据.我需要等待所有订阅完成,然后我的应用程序才能继续.现在,它不等待所有订阅完成,仅完成几个订阅,然后继续进行,而其他订阅在后台继续进行.

I have a subscription inside of a for loop that fetches JSON data as a series of "category data" from an external source, then filters that data based on the users current location. What I need is to wait for all of the subscriptions to complete, and then and only then can my app proceed. Right now, it does not wait for all of the subscriptions to complete, it only completes a few, and then proceeds, while the other subscriptions continue in the background.

我尝试了以下强力"方法,在该方法中,我知道将一定数量的类别添加到过滤后的数组中,并且它可以工作,但是我不知道如何使其在任何情况下都可以工作.

I've tried the following "brute force" method, where i know a certain number of categories will be added to the filtered array, and it works, but I don't know how to make it work for any situation.

这是我的代码:

getMultipleCategoryData(categoryIds: string[]) {
for (let i = 0; i < this.waypointIds.length; i++) {
//after user selects their categories, its added to waypointNames, and occurences() gets the # of occurences of each waypoint name
  let occurences = this.occurences(this.waypointNames[i], this.waypointNames);
  this.categoryApi.getCategoryData(this.waypointIds[i]).toPromise().then(data => {

    let filteredLocs = data.locations.filter(loc => this.distanceTo(loc, this.hbLoc) < MAX_RADIUS);
    let foundLocs = [];
    //fill filteredLocs with first n, n = occurences, entries of data 
    for (let n = 0; n < occurences; n++) {
      if (filteredLocs[n] != undefined) {
        foundLocs[n] = filteredLocs[n];
      }
    }
    //find locations closest to hbLoc (users current location), and add them to waypoints array
    for (let j = 0; j < foundLocs.length; j++) {
      for (let k = 0; k < filteredLocs.length; k++) {
        if (this.distanceTo(this.hbLoc, filteredLocs[k]) < this.distanceTo(this.hbLoc, foundLocs[j]) && foundLocs.indexOf(filteredLocs[k]) < 0) {
          foundLocs[j] = filteredLocs[k];
        }
      }
    }
    if (foundLocs.length > 0 && foundLocs.indexOf(undefined) < 0) {
      for (let m = 0; m < foundLocs.length; m++) {
        this.waypointLocs.push(foundLocs[m]);
      }
    }
  }).then(() => { 
    //this hardcoded, brute force method works, but i'd need it to be more elegant and dynamic
    if (this.waypointLocs.length >= 5) {
      let params = { waypointLocs: this.waypointLocs, hbLoc: this.hbLoc };
      this.navCtrl.push(MapPage, params);
    }
  });
}
}

和categoryApi.getCategoryData方法:

And the categoryApi.getCategoryData method:

getCategoryData(categoryId): Observable<any> {
    // don't have data yet
    return this.http.get(`${this.baseUrl}/category-data/${categoryId}.json`)
        .map(response => {
            this.categoryData[categoryId] = response.json();
            this.currentCategory = this.categoryData[categoryId];
            return this.currentCategory;
        });
}

除了等待订阅完成之外,一切工作都很好,我真的很想一种确定所有订阅何时完成的方法.感谢您的帮助!

Everything is working fine except waiting for the subscriptions to complete, I'd really like a way to determine when all of the subscriptions have completed. Any help is appreciated!

推荐答案

您可以收集数组中的所有可观察对象,并使用

You can collect all observables in an array and use forkJoin to wait for all of them to complete:

let observables: Observable[] = [];
for (let i = 0; i < this.waypointIds.length; i++) {
    observables.push(this.categoryApi.getCategoryData(this.waypointIds[i]))
}
Observable.forkJoin(observables)
    .subscribe(dataArray => {
        // All observables in `observables` array have resolved and `dataArray` is an array of result of each observable
    });

这篇关于在继续操作之前,如何等待for循环内的订阅完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆