Rxjs 如何组合父对象和从属子对象

Rxjs 如何组合父对象和从属子对象,rxjs,Rxjs,有一个不完整的事件对象的连续流。每个项目都有乐队。通过订阅事件,您将获得一个具有多个属性的事件,其中有一个属性“bands”,用于存储bandid数组。有了这些ID,你可以得到每个乐队。(波段流也是连续的。) 问题:最后,您不仅希望有波段,还希望有一个带有波段ID和完整波段对象的完整事件对象 // This is what I could come up with myself, but it seems pretty ugly. getEvents().pipe( switchMap

有一个不完整的事件对象的连续流。每个项目都有乐队。通过订阅事件,您将获得一个具有多个属性的事件,其中有一个属性“bands”,用于存储bandid数组。有了这些ID,你可以得到每个乐队。(波段流也是连续的。)

问题:最后,您不仅希望有波段,还希望有一个带有波段ID和完整波段对象的完整事件对象

// 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};
        })
    })
)

问题:请帮助我找到一种更干净的方法来做这件事(我甚至不确定我的尝试是否产生了预期的结果)。

接受答案

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 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}))
        );
    })
)
此转换返回的可观察对象发出一个具有两个属性的对象:
bandaray
包含使用
getBand
服务检索的频带数组和
event
getEvents
返回的可观察对象发出的对象

还要考虑一下,您正在使用
switchMap
,这意味着只要
getEvents
返回的可观测值发出,您就要切换到最后一次发出,并完成当前可能正在进行的任何操作。换句话说,如果执行
forkJoin
所需的时间比一次发射和另一次
getEvents
发射所需的时间长,则可能会丢失一些事件

如果您不想丢失任何东西,最好使用
mergeMap
而不是
switchMap

更新的答案-可观测波段不完整

在这种情况下,我理解
getBand(bandId)
返回一个可观测值,该值在第一次查询后端时首先发出,然后在后端中的频带数据更改时发出。 如果这是真的,那么你可以考虑这样的事情

getEvents().pipe(
    switchMap(event => {
        return from(event.bands).pipe(
           switchMap(bandId => getBand(bandId)).pipe(
              map(bandData => ({event, bandData}))
           )
        );
    })
)

这种转换产生了一个可观测的信号,它在任何时候发生新事件或波段数据发生变化时都会发出。

你让我意识到我的问题中遗漏了一个细节:事件流和波段都没有完成;两者都是持久性的,并接收连续更新。那么,您通过事件对象接收的BandID数组的含义是什么?您需要ID数组来知道哪些频带链接到特定事件。乐队可能仍会获得对其关联事件没有影响的更新。示例:乐队成员可能会改变。我认为用
combinelateest
替换
forkJoin
,你的第一个建议正是我想要的。