Отображение Observable в элементы массива другого Observable, сглаживание результата

Это название, вероятно, требует дополнительных пояснений.

В основном то, что я получаю от бэкэнда, - это Observable с массивом racedrivers, и каждому из элементов массива я хочу сопоставить другое свойство isOnTrack, которое состоит из другого Observable (простого логического), которое я извлекаю из бэкэнда. Я хочу сгладить конечный результат, чтобы у меня не было Observable внутри Observable. Я пробовал многие операторы 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

После ответа Джонатана я считаю, что мне следовало использовать слово распаковано вместо сглаживания

Observable после преобразований, которые я искал, должен давать что-то похожее на

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},
])

person Peter ten Klooster    schedule 12.06.2020    source источник


Ответы (1)


Имитация функций БД

// 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>[]>
  • ограничьте количество ваших requestOnTrack обновлений до 1 с помощью take(1) => Observable<Observable<T>[]>
  • сопоставить предыдущие значения с новым объектом ({...driver, isOnTrack}) => Observable<Observable<T>[]>
  • mergeAll, чтобы разбить ваш массив на несколько эмитентов mergeAll() => Observable<Observable<T>>
  • combAll, чтобы распаковать наблюдаемые и привязать все отображенные значения к массиву combineAll() => Observable<T[]>

Вот работающий stackblitz

person Jonathan Stellwag    schedule 12.06.2020
comment
Привет, Джонатан, большое спасибо за ответ и потраченное время. Хотя ваш ответ, вероятно, именно то, о чем я просил, последняя наблюдаемая - это не совсем то, что я искал из-за моей плохой формулировки. Последний наблюдаемый объект по-прежнему должен быть массивом драйверов, только с распакованным объектом IsOnTrack Observable. - person Peter ten Klooster; 13.06.2020
comment
@PetertenKlooster, без проблем. Может произойти на этапе разработки. Я обновил свой ответ, чтобы вы получили массив. Следует иметь в виду две вещи. 1. Я использовал take (1), чтобы requestIsOnTrack $ не обновлял результат все время. Измените это, если не хотите. 2. Используя командуcommonAll, вам нужно подождать, пока каждый isOnTrack не выдаст хотя бы одно значение (для каждого драйвера), прежде чем будет выдан окончательный результат. - person Jonathan Stellwag; 13.06.2020
comment
Привет, Джонатан, это отлично работает! большое спасибо. У меня есть немедленный доступ ко всем ценностям, так что это не проблема. - person Peter ten Klooster; 13.06.2020
comment
Я рад, что смог помочь :) - person Jonathan Stellwag; 13.06.2020