Если я правильно понимаю вашу проблему, это могут быть некоторые предложения для решения.
Чтобы сделать вещи немного более понятными, по крайней мере для меня, я бы начал создавать функцию, которая ожидает categoryId
в качестве ввода и возвращает Observable категории, то есть что-то вроде
function getCategory(categoryId: number) {
return this.db.collection('categories').doc(categoryId).valueChanges();
}
Тогда я бы построил Observable, который мне нужен, вот так
wordsCollection.pipe(
mergeMap(words => words),
map(word => {
const categoryRequests = word.categories.map(categoryId => getCategory(categoryId));
return {word: word.word, categoryRequests};
}),
mergeMap(({word, categoryRequests}) => forkJoin(categoryRequests).pipe(map(categories => ({word, categories}))))
)
Здесь ключевыми моментами являются следующие
- Первый
mergeMap
выравнивает массив words
и создает
Наблюдаемый, который испускает каждый элемент массива.
- Во втором операторе,
map
, вы начинаете создавать массив наблюдаемых, который представляет запросы на выборку category
, начиная с его categoryId
, а затем вы возвращаете объект, имеющий оба содержимого word
(я предполагаю, что тип Word
имеет свойство word
, которое содержит фактическое слово) и запросы категории, связанные
- тогда мне нужно использовать
forkJoin
для выполнения запросов, и поэтому я использую mergeMap
для преобразования объекта, возвращенного предыдущим оператором map
, в Observable, который выдает, когда все запросы переводят categoryIds
в categories
на определенное время word
завершили
-
pipe
после forkJoin
просто для создания объекта с word
и categories
свойствами
Поскольку у меня нет готовой среды Firebase, я смоделировал наблюдаемые Firebase с помощью следующего кода
const words = [
{word: 'abc', categories: [1, 2, 3]},
{word: 'cde', categories: [3, 4, 5]},
];
const categories = {
1: 'X',
2: 'Y',
3: 'Z',
4: 'X',
5: 'W',
}
function getCategory(categoryId: number) {
return of(categories[categoryId])
}