在数组项中映射另一个可观察量,使结果展平



这个标题可能需要更多解释。

基本上,我从后端得到的是一个带有赛车手数组的可观察量,并且对于每个数组项,我想映射另一个属性是OnTrack,它由我从后端检索的另一个可观察量(简单布尔值(组成。我想展平最终结果,这样我就没有可观察量中的可观察量。我已经尝试了许多 rxjs 运算符,但我无法让它工作。

不起作用的代码:

this.drivers$ = this.db.list('users').valueChanges().pipe(
map(arr => arr.map( (driver:any) => {
driver.isOnTrack = this.db.object(`telemetry/${driver.uid}/values/IsOnTrack`).valueChanges();
return driver
})),
mergeAll()
);

这成功地将可观察的 isOnTrack 映射到数组项目,但我无法将其展平。

项目在 RxJS 6 上

更新 1

在乔纳森的回答之后,我相信我应该使用解压缩这个词而不是扁平化

我要寻找的转换后的可观察对象应该提供类似于

of([
{id: 1, name: 'foo', isOnTrack: true},
{id: 2, name: 'bar', isOnTrack: true},
{id: 3, name: 'baz', isOnTrack: false},
])

在后端更改一个 IsOnTrack 后,它应该再次发出完整的数组。

of([
{id: 1, name: 'foo', isOnTrack: false},
{id: 2, name: 'bar', isOnTrack: true},
{id: 3, name: 'baz', isOnTrack: false},
])

模拟数据库函数

// this.db.list('users').valueChanges()
const requestIsOnTrack$ = (id: number): Observable<boolean> => interval(1000).pipe(
take(3),
map(() => Math.random() >= 0.5)
)
// this.db.object(`telemetry/${driver.uid}/values/IsOnTrack`).valueChanges()
const requestDrivers$ = () => of([
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'baz'},
])

实现

const drivers$ = requestDrivers$().pipe(
map(drivers => drivers.map(driver => requestIsOnTrack$(driver.id).pipe(
take(1),
map(isOnTrack => ({
...driver,
isOnTrack
}))
))),
mergeAll(),
combineAll()
)

解释

存在于可观察量中的对象类型只是为了便于不使用接口而<T>

  • 从数据库请求所有驱动程序:requestDrivers$() => Observable
  • 将请求isOnTrack映射到每个驱动程序requestIsOnTrack$(id) => Observable<Observable<T>[]>
  • 使用take(1) => Observable<Observable<T>[]>requestOnTrack更新限制为 1
  • 将以前的值映射到新对象({...driver, isOnTrack}) => Observable<Observable<T>[]>
  • mergeAll 将数组拆分为多个发射mergeAll() => Observable<Observable<T>>
  • combineAll 以取消对可观察量的装箱,并将所有映射的值绑定到数组combineAll() => Observable<T[]>

这是一个正在运行的堆栈闪电战