是的,forkJoin 可用于获取内部 observables 的数据:
getAllTours (cityId) {
return this.af.database
.list(`/cities/${cityId}/tours`)
.mergeMap((tours) => {
// The array of tours is going to be mapped to an observable,
// so mergeMap is used.
return Observable.forkJoin(
// Map the tours to the array of observables that are to
// be joined. Note that forkJoin requires the observables
// to complete, so first is used.
tours.map((tour) => this.af.database
.object(`/tours/${tour.$key}/tours`)
.first()
),
// Use forkJoin's results selector to match up the result
// values with the tours.
(...values) => {
tours.forEach((tour, index) => { tour.tour = values[index]; });
return tours;
}
);
});
}
是否使用forkJoin 是正确的方法将取决于您的要求。
使用上面的代码,getAllTours 返回的 observable 将不会发出值,直到所有内部 observable 都完成 - 也就是说,直到每个城市的游览都被查找完。这可能会影响 感知 性能 - 如果在查找 /tours/${tour.$key}/tours 中的信息之前可以显示 /cities/${cityId}/tours 中的信息,您将无法显示它。同样,您将无法在结果到达时显示该城市的游览。
使用forkJoin 使处理实现更简单,但它可能会使UI 感觉更慢。 (但是,您可能不希望对 UI 进行零碎更新。)
请注意,如果您确实需要在视图中显示每个城市的游览之前对其进行一些处理,您也许可以对问题代码中的 observables 执行上述处理。例如,使用您的 getAllTours 函数:
observable = getAllTours(someCityId);
observable.map((tours) => {
tours.forEach((tour) => {
// With your function, tour.tour is an observable, so map
// could be used to process the values.
tour.tour = tour.tour.map((value) => {
// Do some processing here with the value.
})
// And, if you are not interested in dynamic updates, you could
// call first.
.first();
});
return tours;
});
然后您可以在模板中使用async 管道,它会接收您处理过的游览。