RxJS:沿可观察链传递数据的干净方法?

时间:2019-06-05 22:26:54

标签: typescript rxjs

我似乎经常遇到这种情况,我需要沿着流链传递数据。换句话说,我的可观察对象取决于一个或多个其他可观察对象的输出。

下面是一个简单示例的3种方法,但没有一种感觉像“ RxJS”方法。有更好的方法吗?

// Method #1 - looks clean, but feels hacky

let firstResponse = null;
performFirstAction().pipe(
  tap(_firstResponse => (firstResponse = _firstResponse)),
  switchMap(_firstResponse => performSecondAction(_firstResponse)),
  switchMap(secondResponse => performThirdAction(firstResponse, secondResponse))
);

// Method #2 - gets ugly real quick as it scales

performFirstAction().pipe(
  switchMap(firstResponse =>
    performSecondAction(firstResponse).pipe(
      map(secondResponse => ({ firstResponse, secondResponse }))
    )
  ),
  switchMap(({ firstResponse, secondResponse }) =>
    performThirdAction(firstResponse, secondResponse)
  )
);

// Method #3 - might as well just use callbacks at this point

performFirstAction().pipe(
  switchMap(firstResponse =>
    performSecondAction(firstResponse).pipe(
      switchMap(secondResponse =>
        performThirdAction(firstResponse, secondResponse)
      )
    )
  )
);

2 个答案:

答案 0 :(得分:0)

您的情况还有另一种方法

performFirstAction().pipe(
  switchMap(first =>
    performSecondAction(first).pipe(mergeMap(second=>performThirdAction(first, second)))
    )
  ),
);

基本上,您将first作为局部变量,因此,如果您有第四个调用,则可以使用类似的模式并将其嵌套。

,如果需要通用模式,可以尝试通过创建高阶函数以返回可观察值来mergeScan。这里acc始终是最后一个可观察到的返回值

from([first,first=>second(first),second=>third(second)])
.pipe(mergeScan((acc,currObs)=>currObs(acc),null))

答案 1 :(得分:0)

最干净,最易读的方法是将中间可观察对象存储在其自己的变量中

const firstResponse$ = performFirstAction();

const secondResponse$ = firstResponse$.pipe(
  switchMap(firstResponse => performSecondAction(firstResponse)),
);

const thirdResponse$ = secondResponse$.pipe(
  withLatestFrom(firstResponse$),
  switchMap((secondResponse, firstResponse) => performThirdAction(firstResponse, secondResponse))
);