switchMap с forkJoin не показывает результатов

#angular #rxjs

#angular #rxjs

Вопрос:

Мой вариант использования таков: я должен получить MeasurementUnit для каждого ProductCategory , выполнив вызов api для каждого ProductCategory .

Это фрагмент из одного из моих сервисов. Когда findAll подписывается на компонент, он никогда не получает значения. Однако некоторые значения регистрируются как отмеченные. Что я делаю не так?

Есть ли альтернативный подход для получения тех же результатов?

 findAll(): Observable<ProductCategory[]> {
  return this.http.get<UnresolvedProductCategory[]>(`product-categories/`).pipe(
    tap(categories => console.log(categories)),  // is logged
    switchMap(categories => forkJoin(categories.map(this.resolveCategory.bind(this)))),
    tap(categories => console.log({ finalCategories: categories })) // is not logged
  );
}

resolveCategory(category: UnresolvedProductCategory): Observable<ProductCategory> {
  return this.measurementUnits.findOne(category.measurementUnit).pipe(
    map(measurementUnit => ({ ...category, measurementUnit })),
    tap(category => console.log({ category })) // is logged for each category
  );
}
 

Комментарии:

1. Если все исходные наблюдаемые внутри forkJoin не завершаются, он никогда не будет выдавать. действительно measurementUnits.findOne() ли наблюдаемое завершено? Если нет, возможно, добавьте take(1) к нему.

2. measurementUnits.findOne выполняет другой вызов api с использованием http.get . Если я не ошибаюсь, http.get завершается после возврата одного значения, не так ли?

3. Да, так и должно быть. Вы могли бы попробовать с take(1) помощью, чтобы увидеть, имеет ли это значение.

Ответ №1:

forkJoin будет выдавать только после завершения всех исходных наблюдаемых.

Вы могли бы использовать combineLatest вместо этого, который будет излучать один раз, когда все исходные наблюдаемые будут излучать хотя бы один раз.


В качестве альтернативы, вы могли бы использовать take(1) , чтобы убедиться, что все исходные наблюдаемые завершены после первого выпуска:

 findAll(): Observable<ProductCategory[]> {
  return this.http.get<UnresolvedProductCategory[]>(`product-categories/`).pipe(
    tap(categories => console.log(categories)),
    switchMap(categories => forkJoin(categories.map(
      this.resolveCategory.bind(this).pipe(take(1))
    ))),
    tap(categories => console.log({ finalCategories: categories }))
  );
}
 

Комментарии:

1. Уточните еще одну вещь, this.resolveCategory на самом деле используется другой вызов api http.get , и он завершается после отправки один раз (потому что значения регистрируются, как указано в исходном фрагменте). Ошибок также нет. Что дает? Это действительно работало с использованием combineLatest . Но почему это не forkJoin работает?