有一系列不完整的事件对象。每个事件都有乐队。通过订阅事件,您将获得一个具有多个属性的事件,其中包括一个属性“ bands”,用于存储bandId数组。使用这些ID,您可以获得每个频段。 (乐队的流也是连续的。)
问题:最后,您不仅要拥有乐队,而且要拥有带有bandId和完整band对象的完整事件对象。
// This is what I could come up with myself, but it seems pretty ugly.
getEvents().pipe(
switchMap(event => {
const band$Array = event.bands.map(bandId => getBand(bandId));
return combineLatest(of(event), ...band$Array);
})),
map(combined => {
const newEvent = combined[0];
combined.forEach((x, i) => {
if (i === 0) return;
newEvent.bands = {...newEvent.bands, ...x};
})
})
)
问题:请帮助我找到一种更清洁的方法(而且我不确定我的尝试是否会产生预期的结果)。
答案 0 :(得分:2)
接受的答案
getEvents().pipe(
switchMap(event => {
const band$Array = event.bands.map(bandId => getBand(bandId));
return combineLatest(band$Array).pipe(
map(bandArray => ({bandArray, event}))
);
})
)
原始答案
您可能想尝试以下方法
getEvents().pipe(
switchMap(event => {
const band$Array = event.bands.map(bandId => getBand(bandId));
return forkJoin(band$Array).pipe(
map(bandArray => ({bandArray, event}))
);
})
)
此转换返回的Observable发出一个具有2个属性的对象:bandArray
保留使用getBand
服务检索的波段数组,而event
则是返回的Observable发出的对象由getEvents
。
还请考虑您正在使用switchMap
,这意味着getEvents
返回的Observable发射后,您将立即切换到最后一个发射,并完成所有可能在运行中的操作。时刻。换句话说,如果执行forkJoin
所需的时间长于一次发射和另一次getEvents
的发射时间,则可以松开某些事件。
如果您不想丢失任何东西,则最好使用mergeMap
而不是switchMap
。
更新后的答案-可观察范围未完成
在这种情况下,我了解到getBand(bandId)
返回一个Observable,它在第一次查询后端时,然后在后端中的band数据更改时,首先发出。
如果这是真的,那么您可以考虑这样的事情
getEvents().pipe(
switchMap(event => {
return from(event.bands).pipe(
switchMap(bandId => getBand(bandId)).pipe(
map(bandData => ({event, bandData}))
)
);
})
)
此转换会产生一个Observable,它可以在新事件发生时或波段数据更改时发出。