ForEach 比我的 Observable returns 值更快

ForEach is faster than my Observable returns values

我有以下代码:

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],它会 return 一个结果。

理论上这应该可行,但考虑到我从 Firebase 数据库查询,Observable 在那里有时间滞后,我无法足够快地获取值。我怀疑和我读到的另一件事是,如果在当前完成之前启动另一个,则 Observables 可能会被取消。但是当我 运行 我的代码时,这似乎不是问题。

如果要按顺序处理该列表,则需要等待 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()