我对内部Observables有疑问。
const wordsCollection = this.db.collection('words').valueChanges();
return wordsCollection.pipe(
map((words: Word[]) => {
return words.map((word: Word) => {
const categories = word.categories.map((categoryId: string) => {
return this.db.collection('categories').doc(categoryId).valueChanges().pipe(
map((category: Category) => {
return category;
})
);
});
return {
...word,
categories: categories
};
});
})
);
结果类似于:
{
word: 'blabla',
categories: Observable (instead of for example 'english')
}
我知道我需要使用forJoin之类的东西,但是不知道如何正确使用它。有帮助吗?
答案 0 :(得分:1)
如果我正确理解您的问题,则可能是解决方案的一些建议。
至少对于我来说,为了使事情更清楚一点,我将开始创建一个函数,该函数期望输入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
数组并创建一个
Observable发出数组的每个元素。map
中,您开始创建一个Observables数组,该数组表示从category
开始提取categoryId
的请求,然后返回一个对象,该对象具有word
的内容(我假设类型Word
的属性word
包含实际单词)和关联的类别请求forkJoin
来执行请求,因此我使用mergeMap
将前一个map
运算符返回的对象转换为一个Observable,该对象将在所有请求翻译时发出从categoryIds
到categories
到某个word
已完成pipe
之后的forkJoin
只是用来创建具有word
和categories
属性的对象由于我没有随时可用的Firebase环境,因此我使用以下代码模拟了Firebase Observables
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])
}
答案 1 :(得分:0)
尝试一下:
const wordsCollection = this.db.collection('words').valueChanges();
return wordsCollection.pipe(
mergeMap((words: Word[]) => Rx.of(...words).pipe(
mergeMap((word: Word) => Rx.of(...word.categories).pipe(
mergeMap(categoryId => this.db.collection('categories').doc(categoryId).valueChanges()),
toArray(),
map(categories => ({
...word,
categories
}))
))
))
);