#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
на самом деле используется другой вызов apihttp.get
, и он завершается после отправки один раз (потому что значения регистрируются, как указано в исходном фрагменте). Ошибок также нет. Что дает? Это действительно работало с использованиемcombineLatest
. Но почему это неforkJoin
работает?