如何映射观察到的数组以组合多个可观察到的最新值

How to map over an observed array to combine multiple obervables latest values

我正在通过管道连接到一个 Observable 中,它会传输一系列比方说食物。我需要得到最新的厨师、最新的厨房和用于准备这些食物的最新刀。这三个值都是通过像 getCookById(food.cook.id) 这样的可观察对象获得的值。 我怎么能这样映射它:

{
   foodItem,
   cook,
   kitchen,
   knife
}

目前,我得到了一个空项目数组,就像这样:

    const foodObservable = new Subject();
    
    foodObservable.pipe(
      map(foodItems => {
        return foodItems.map((foodItem: any)=>{
          const cookObservable = new Subject();
          const kitchenObservable = new Subject();
          const knifeObservable = new Subject();

          combineLatest(cookObservable, kitchenObservable, knifeObservable).subscribe(([cook, kitchen, knife]) => {
            return {
              foodItem,
              cook,
              kitchen,
              knife
            };
          });
        })
      })
    ).subscribe(foodPreparationArray=>{
      console.log(foodPreparationArray) // array of empty values :(
    })

根据您的情况和评论,我建议进行以下更改

  1. 您需要使用像 switchMap 这样的高阶映射运算符来从一个可观察对象映射到另一个。 map 运算符用于转换发出的数据。

  2. 使用 Firebase get() 而不是 valueChanges() 会更合适。我假设您此时需要该值并且不需要观察 属性 的任何变化。有关详细信息,请参阅

  3. 使用 get() 而不是 valueChanges() 为我们提供了完成而不是流式传输的可观察对象。因此,您可以将 combineLatest 替换为 forkJoin

  4. 你需要两个 forkJoin。第一个 forkJoin 是触发对 foodItems 数组的每个元素的请求,第二个 forkJoin 是触发对 cookknife 和 [=25= 的请求]同时

  5. 您终于可以使用 map 运算符来组合所有内容了。

尝试以下方法

foodObservable.pipe(
  switchMap((foodItems: any) =>                                            // <-- RxJS `switchMap` operator
    forkJoin(
      foodItems.map((foodItem: any) =>                                     // <-- JS `Array#map` function
        forkJoin({
          cook: db.collection('cook').doc(foodItem.cookId).get(),
          kitchen: db.collection('kitchen').doc(foodItem.kitchenId).get(),
          knife: db.collection('knife').doc(foodItem.knifeId).get()
        }).pipe(
          map(({cook, kitchen, knife}) => ({                               // <-- RxJS `map` operator
            ...foodItem,                                                   // <-- spread operator
            cook: cook,
            kitchen: kitchen,
            knife: knife
          )})
        )
      )
    )
  )
).subscribe({
  next: (foodPreparationArray: any) => {
    console.log(foodPreparationArray);
  },
  error: (error: any) => {
    // handle error
  }
});