@ Дофламинго указал нам в направлении forkJoin, а @ Llorenç привел отличный пример кода с картой и уменьшил количество каналов, чтобы объединить Observables в один Observable. Для меня forkJoin потерпел неудачу, если у некоторых авторов не было Книг. Так что я закончил тем, что пошел с CombineLatest (который не ждет завершения всех наблюдаемых). Это мой окончательный код (вся заслуга @ Llorenç):
mockBooks$(key): Observable<Book[]> {
return this.afs.collection<Book>('books', ref =>
ref.where('private', '==', true)
.where('authors', 'array-contains', key)
).valueChanges()
// return of([key + '-book1', key + '-book2', key + '-book3']);
}
getPrivateBooksFromAuthors(authors): Observable<Book[]> {
let bookRefs: Observable<Book[]>[] = authors.map(key => this.mockBooks$(key));
// return combineLatest(bookRefs).pipe(
// tap((books) => console.log('After forkJoin', books)),
// // You need this flattening operation!!
// map(books => books.reduce((acc, cur) => [...acc, ...cur], []) ));
return combineLatest<Book[]>(bookRefs).pipe(
map(arr => arr.reduce((acc, cur) => acc.concat(cur) ) ),
)
}
Я закомментировал код Ллоренса, чтобы показать разницу. Спасибо вам обоим!