ForEach比我的Observable返回值更快

时间:2017-07-26 10:31:16

标签: javascript angular firebase rxjs angularfire2

我有以下代码:

evaluateLocations() {
  const locs = this.currentTour.locIds;
  let lastLoc = null;
  locs.forEach(loc => {
    console.log(lastLoc, loc);
    if (lastLoc !== null) {
      console.log('if durch', lastLoc, loc);
      this.afDb.list('routes', {
        query: {
          orderByChild: 'idStart',
          equalTo: loc
        }
      }).switchMap(items => {
        console.log('switchMap starts', lastLoc, loc); //here the output is always lastLoc = loc while it shouldn't be that
        const filtered = items.filter(item => item.idEnd === lastLoc);
        const route = filtered[0];
        return Observable.of(route);
      }).subscribe();
    }
    lastLoc = loc;
  });
}

现在,在switchMap发挥作用的时候,forEach循环似乎已经完成,因此过滤总是错误的。

我的逻辑是:
我想循环遍历一系列ID。然后我调用数据库,获取起点为locs[n]的所有条目。然后我想过滤locs[n+1],它会返回一个结果。

理论上这应该有效,但鉴于我从Firebase数据库查询,Observable在那里有一个时间滞后,我无法快速得到这些值。我怀疑和我读到的另一件事是,如果在当前的一个完成之前启动另一个Observables,则update wp_posts set post_status = 'wc-completed' where post_type = 'shop_order' and post_status ='wc-processing' ; 可能被取消。但是当我运行我的代码时,这似乎不是一个问题。

1 个答案:

答案 0 :(得分:2)

如果要按顺序处理该列表,则需要等待Observable的操作完成。这是一种惯用的方式seems to beObservable转换为Promiseawait

将其应用于您的代码:

async evaluateLocations() { // <-- make method async, so we can use await
  const locs = this.currentTour.locIds;
  let lastLoc = null;
  for (let locKey in locs) { // <-- use regular for-in loop
    let loc = locs[locKey];
    console.log(lastLoc, loc);
    if (lastLoc !== null) {
      console.log('if durch', lastLoc, loc);
      await this.afDb.list('routes', { // <-- use await here
        query: {
          orderByChild: 'idStart',
          equalTo: loc
        }
      }).switchMap(items => {
        console.log('switchMap starts', lastLoc, loc); //here the output is always lastLoc = loc while it shouldn't be that
        const filtered = items.filter(item => item.idEnd === lastLoc);
        const route = filtered[0];
        return Observable.of(route);
      }).toPromise(); // <-- convert to Promise
    }
    lastLoc = loc;
  }
}

不要忘记你现在需要在调用函数中等待evaluateLocations(),如果你之后需要做一些依赖于evaluateLocations()结果的事情。