rxjs:切换switchMap后访问原始可观察结果

时间:2020-09-14 14:41:26

标签: rxjs rxjs6 rxjs-pipeable-operators switchmap

resultB被操作后,如何在tap操作符中访问switchMap

streamA$.pipe(
    switchMap(resultA => {
        const streamB$ = resultA ? streamB1$ : streamB2$;

        return streamB$.pipe(                   // <- nesting
            switchMap(resultB => loadData(resultB)),
            tap(data => {
                // how do I access resultB here?
            })
        );

    })
);

奖金问题: 是否可以避免在此处嵌套,并将整个流链接在单个管道下?

3 个答案:

答案 0 :(得分:2)

请考虑以下示例:

CookieManager.java

答案 1 :(得分:1)

这是您如何编写可观察变量以访问resultB并平整可观察运算符链的方法-

streamA$.pipe(        
    switchMap(resultA => iif(() => resultA ? streamB1$ : streamB2$),
    switchMap(resultB => forkJoin([loadData(resultB), of(resultB)])),
    tap(([loadDataResponse, resultB]) => {
        //loadDataResponse - This will have response of observable returned by loadData(resultB) method
        //resultB - This is resultB
    })
);

答案 2 :(得分:1)

这里的基本问题是switchMap用于转换值以将特定形状发射到流中。如果您的resultB值不是该形状的一部分,那么位于链下游的操作员将无法访问它,因为它们仅接收发射的形状。

因此,基本上有两种选择:

  • 传递包含您的值的中间形状
  • 使用嵌套管道将两段数据都放入同一个运算符范围

到目前为止,建议的解决方案包括映射到中间对象。我的首选是使用嵌套管道,因此流经流的数据具有有意义的形状。但是,这实际上取决于偏好。

使用嵌套管道,您的代码将如下所示:

streamA$.pipe(
    switchMap(resultA => {
        const streamB$ = resultA ? streamB1$ : streamB2$;

        return streamB$.pipe(
            switchMap(resultB => loadData(resultB).pipe(
                tap(data => {
                    // you can access resultB here
                })
            ))
        );
    })
);

注意:您可以使用iif有条件地选择源流:

streamA$.pipe(
    switchMap(resultA => iif(()=>resultA, streamB1$, streamB2$).pipe(
        switchMap(resultB => loadData(resultB).pipe(
            tap(data => {
                // you can access resultB here
            })
        ))
    ))
);

将某些逻辑分解为单独的功能可能会有所帮助:

streamA$.pipe(
    switchMap(resultA => doSomeWork(resultA)),
    miscOperator1(...),
    miscOperator2(...)
);

doSomeWork(result) {
    return iif(()=>result, streamB1$, streamB2$).pipe(
        switchMap(resultB => loadData(resultB).pipe(
            tap(data => {
                // you can access resultB here
            })
        ))
    ))
}