Concat可观察性重用先前的结果



想象一下,我有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个(?

您可以尝试类似的东西

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

整个想法是使用switchMap从源Observable切换到传递给switchMap的函数作为参数返回的Observable。

也许值得一提的是使用了链接到第一个switchMap的管道中的mapmap运算符确保我们将cat作为传递第二个也是最后一个switchMap的参数的一部分。

UPDATE after comment如果函数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}))))
)
}

最新更新