rxjs:在 switchMap'ped 之后访问原始 observable 的结果
rxjs: access the result of original observable after it was switchMap'ped
如何在 tap
运算符 switchMap
ped 之后访问 resultB
?
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?
})
);
})
);
奖金问题:
是否可以避免这里的嵌套,将整个流程链在单管道下?
请考虑以下示例:
streamA$.pipe(
switchMap(resultA => resultA ? streamB1$ : streamB2$),
switchMap(resultB => loadData(resultB).pipe(map(x => [resultB, x]))),
tap([resultB, data] => {})
);
这就是您如何编写可观察对象以访问 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
})
);
这里的基本问题是 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
})
))
))
}
如何在 tap
运算符 switchMap
ped 之后访问 resultB
?
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?
})
);
})
);
奖金问题: 是否可以避免这里的嵌套,将整个流程链在单管道下?
请考虑以下示例:
streamA$.pipe(
switchMap(resultA => resultA ? streamB1$ : streamB2$),
switchMap(resultB => loadData(resultB).pipe(map(x => [resultB, x]))),
tap([resultB, data] => {})
);
这就是您如何编写可观察对象以访问 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
})
);
这里的基本问题是 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
})
))
))
}