Reputation: 10045
How do I access the resultB
in the tap
operator after it was switchMap
ped ?
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?
})
);
})
);
bonus question: Is it possible to avoid the nesting here, and chain the whole flow under single pipe?
Upvotes: 2
Views: 69
Reputation: 14750
The basic problem here is that switchMap
is being used to transform values to emit a certain shape into the stream. If your resultB
value isn't part of that shape, then operators further down the chain won't have access to it, because they only receive the emitted shape.
So, there are basically 2 options:
The solutions suggested so far involve mapping to an intermediate object. My preference is to use the nested pipe, so the data flowing through the stream is a meaningful shape. But, it really comes down to preference.
Using the nested pipe, your code would look something like this:
streamA$.pipe(
switchMap(resultA => {
const streamB$ = resultA ? streamB1$ : streamB2$;
return streamB$.pipe(
switchMap(resultB => loadData(resultB).pipe(
tap(data => {
// you can access resultB here
})
))
);
})
);
Note: you can use iif
to conditionally choose a source stream:
streamA$.pipe(
switchMap(resultA => iif(()=>resultA, streamB1$, streamB2$).pipe(
switchMap(resultB => loadData(resultB).pipe(
tap(data => {
// you can access resultB here
})
))
))
);
It can be helpful to break out some of the logic into separate functions:
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
})
))
))
}
Upvotes: 1
Reputation: 5602
This is how you can write your observable to get access of resultB
and flat the observable operators chain -
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
})
);
Upvotes: 1
Reputation: 6422
Please consider the following example:
streamA$.pipe(
switchMap(resultA => resultA ? streamB1$ : streamB2$),
switchMap(resultB => loadData(resultB).pipe(map(x => [resultB, x]))),
tap([resultB, data] => {})
);
Upvotes: 2