首页 > 解决方案 > 如何正确使用forkJoin

问题描述

我对内部 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 的东西,但不知道如何正确使用它。有什么帮助吗?

标签: javascriptfirebaserxjsgoogle-cloud-firestoreobservable

解决方案


如果我正确理解您的问题,这些可能是一些解决方案的建议。

为了让事情稍微清楚一点,至少对我来说,我将开始创建一个函数,它期望 acategoryId作为输入并返回该类别的 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将 Array 展平words并创建一个 Observable,该 Observable 发出 Array 的每个元素。
  • 在第二个运算符 中,您开始创建一个 Observables 数组,它表示从其map获取开始的请求,然后返回一个对象,该对象同时具有(我假设该类型具有包含实际word) 和相关的类别请求categorycategoryIdwordWordword
  • 然后我需要用来forkJoin执行请求,因此我用来mergeMap将前一个运算符返回的对象转换map为一个 Observable,当所有要转换为某个特定的请求categoryIdscategories完成word时发出
  • 之后pipe只是forkJoinwordcategories属性创建对象

由于我没有现成的 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])
}

推荐阅读