在 AngularFire 中使用 forkJoin 运行 多个并发查询

Using forkJoin to run multiple concurrent queries with AngularFire

问题

我正在使用 AngularFire2 并且想要 return 与两个或更多联系人姓名关联的数据。

例如,在我的实时数据库中查询 contactNames Steve 和 Brandon:

permits: {
  1: {
    permit: '12345',
    contactName: 'Steve'
  },
  2: {
    permit: '45678',
    contactName: 'Brandon'
  },
  3: {
    permit: '78910',
    contactName: 'Kevin'
  },
  4: {
    permit: '54321',
    contactName: 'Steve'
  },
}

会return

  1: {
    permit: '12345',
    contactName: 'Steve'
  },
  2: {
    permit: '45678',
    contactName: 'Brandon'
  },
  4: {
    permit: '54321',
    contactName: 'Steve'
  },

我的解决方案尝试

我正在使用 map 循环遍历并将可观察对象存储在数组中

contactNamesFilter: string[] = ['Steve', 'Brandon'];

const requests = this.contactNamesFilter
  .map(contactName => this.permitBrowserService.getData(contactName));

和 forkJoin 将它们全部合并为一个可观察对象。 (我使用的是 RxJS v6.6.3)

forkJoin(requests).subscribe(console.log);

问题是订阅 forkJoin observable 并没有 return 任何东西。看起来代码已经死了,而不是 运行。我知道 forkJoin 不会 return 任何东西,直到所有 observables 都有 returned 东西。我怀疑这与 permitBrowserService.getData() observable 在技术上是相同的有关。

我做错了什么?有没有更好的方法来解决这个问题?

其他疑难解答

我尝试明确地写出具有相同结果的可观察源:

forkJoin({
  sourceOne: this.permitBrowserService.getData('Steve'),
  sourceTwo: this.permitBrowserService.getData('Brandon'),
}).subscribe(console.log);

备份

我正在使用 AngularFire2 查询许可列表:

export class PermitBrowserService {
  permitData$: Observable<AngularFireAction<DataSnapshot>[]>;
  contactName$: BehaviorSubject<string|null>;

  constructor(
    public db: AngularFireDatabase,
  ) {
    this.contactName$ = new BehaviorSubject(null);
    this.permitData$ = this.contactName$.pipe(
      switchMap(contactName => 
        db.list('/permits', ref =>
          contactName ? ref.orderByChild('contactName').equalTo(contactName) : ref
        ).snapshotChanges()
      )
    );
  }

  getData(contactNameFilter?: string | null): Observable<WellPermit[]> {
    if (contactNameFilter) {
      this.contactName$.next(contactNameFilter);
    }
    return this.permitData$.pipe(
      map(changes => {
        return changes.map(c => {
          const data = c.payload.val();
          const id = c.key;
          return { id, ...data };
        })
      })
    );
  }

因为你的 this.permitData$ (permitBrowserService.getData()) 永远不会完成,forkJoin 永远不会发出任何东西。所以使用 combineLatest,它会在每次 this.permitData$ 发出时发出。

combineLatest({
  sourceOne: this.permitBrowserService.getData('Steve'),
  sourceTwo: this.permitBrowserService.getData('Brandon'),
}).subscribe(console.log);

const requests = this.contactNamesFilter
  .map(contactName => this.permitBrowserService.getData(contactName));

combineLatest([...requests]).subscribe(console.log);

combineLatest

Combines multiple Observables to create an Observable whose values are calculated from the latest values of each of its input Observables.

forkJoin

Accepts an Array of ObservableInput or a dictionary Object of ObservableInput and returns an Observable that emits either an array of values in the exact same order as the passed array, or a dictionary of values in the same shape as the passed dictionary.