Наблюдаемые конкататы, использующие предыдущие результаты - PullRequest
0 голосов
/ 14 ноября 2018

Представьте, что у меня есть 3 функции, которые принимают некоторые аргументы и возвращают наблюдаемые.Логика будет (все будет результатом чего-то асинхронного):

  1. Получить кошку.
  2. Пэт кошку.
  3. Получить корм для кошки на основеэто настроение после ласки

Пример кода:

function getCat(): Observable<Cat> {
  return Observable.of({ name: 'Larry' }) 
}

function petCat(cat: Cat): Observable<Mood> {
  return Observable.of(Mood.HAPPY)
}

function getFood(cat: Cat, mood: Mood): Observable<Food> {
  return Observable.of({ type: 'fish' })
}
  1. Я хотел бы получить Observable, эквивалентный этому:

    Observable.from([{ name: 'Larry' }, Mood.HAPPY, { type: 'fish' }])

  2. Я бы хотел, чтобы функции вызывались последовательно (очевидно из сигнатур параметров)

  3. Я не хотел бы откладывать отдельные выбросы вЯ хочу получить результаты, как только они появятся.

Я могу заставить его работать с чем-то вроде этого:

function perform() {
  return getCat().pipe(
    mergeMap((cat) => concat(
        of(cat),
        petCat(cat).pipe(
          mergeMap((mood) => concat(
            of(mood),
            getFood(cat, mood)
          ))
        )
      )
    ),
  )
}

Вопрос в том , есть ли лучший, более читабельный способ сделать это (скажем, у меня будет 5 из них, которые я бы хотел объединить)?

1 Ответ

0 голосов
/ 14 ноября 2018

Вы можете попробовать что-то вроде

getCat()
.pipe(
   switchMap(cat => petCat(cat).pipe(map(mood => ({cat, mood})))),
   switchMap(({cat, mood}) => getFood(cat, mood))
)

Вся идея состоит в том, чтобы использовать switchMap к переключателю из источника Observable в Observable, возвращаемого функцией, переданной в switchMap в качестве параметра.

Возможно, стоит упомянуть использование map, прикованного цепью к трубе первого switchMap. Этот оператор map гарантирует, что мы сохраняем cat как часть параметров, которые передаем второму и последнему, switchMap.

ОБНОВЛЕНИЕ после комментария Если функция perform должна излучать все 3 элемента, испускаемые этими 3 функциями, вы можете попробовать что-то вроде следующего

function perform() {
   return getCat()
          .pipe(
             switchMap(cat => petCat(cat).pipe(map(mood => ({cat, mood})))),
             switchMap(({cat, mood}) => getFood(cat, mood).pipe(map(food => ({cat, mood, food}))))
          )
}
...