I need to compose one Observable from values of two another Observables. The answer is zip operator. But my case is more complicated. I have an id of A.
A {id, name, idOfRelatedB} //first observable
B {...} // second
So, in order to get B, I need to get A before to retrieve an id of B. And finally I need to return an Observable with A and B. How to deal with that in RX.
My unsuccessful solution in angular/typescript:
@Injectable()
export class StrategyResolver implements Resolve<StrategyWithSourceCode> {
constructor(private strategyService: StrategyService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
const strategyId = route.paramMap.get('strategyId');
let sourceCodeObs: Observable<SourceCode>;
let strategy: Strategy;
this.strategyService.getStrategy(parseInt(strategyId)).subscribe(value => {
strategy = value;
sourceCodeObs = this.strategyService.getStrategySource(parseInt(strategyId), strategy.sourceCodeId);
});
return zip(of(strategy), sourceCodeObs, (v1: Strategy, v2: SourceCode) => ({v1, v2}));
}
}
Upd: correct solution with help of user madjaoue (thanks for him) with any specific of rxjs 6.
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
const strategyId = route.paramMap.get('strategyId');
return this.strategyService.getStrategy(parseInt(strategyId)).pipe(
concatMap(strategy => {
let sourceCodeObs = this.strategyService.getStrategySource(parseInt(strategyId), strategy.sourceCodeId);
return zip(of(strategy), sourceCodeObs, (v1: Strategy, v2: SourceCode) => ({v1, v2}));
})
)
}
You weren't so far from the answer. This is a slight modification of your code that does what you want.
const strategyObs = this.strategyService.getStrategy(parseInt(strategyId));
// use concatMap to combine two streams
strategyObs.concatMap(strategy => {
let sourceCodeObs = this.strategyService.getStrategySource(parseInt(strategyId), strategy.sourceCodeId);
// zip the response of the first service with the second
return zip(Observable.of(strategy), sourceCodeObs)
});
.subscribe( ([A, B]) => ...)
Note that you can replace concatMap
by other operators like switchMap
, mergeMap
or exhaustMap
for example. All will combine your streams, but not in the same way. Please check that concatMap
is suitable for your case.