Reputation: 1927
I have a combination of several async request I need to complete together (doing it with forkJoin) - when doing so, I initiate an object:
export class fullData
{
AProp : any;
BProp : any;
CProp : any;
}
const fullDataObservable : fullData = forkJoin(
{
AProp : this.myFirstSrv.getAProp(),
BProp : this.mySecondsSrv.getBProp(),
CProp : this.myThirdSrv.getCProp()
});
return fullDataObservable;
So far - so good. Now - I have 3 new properties in this object:
export class fullData
{
AProp : any;
BProp : any;
CProp : any;
prop1 : any;
prop2 : any;
prop3 : any;
}
the first of then (prop1) depend on the CProp value (or this.myThirdSrv.getCProp()) as a parameter, when doing a get request, the second (prop2) is a simple manipulation of the first one, and the third one (prop3) is also depending on the second as a parameter in a get request. I've tried using a mergeMap, but it didn't work. What am I doing wrong ?:
gatherAllRelevantData() : any
{
//this.myService.getProp1() return observable after get request
this.myService.getProp1().pipe
(
mergeMap((prop1Value : any[]) =>
{
//this.myService.getResultAfterSimpleManipulation return object, not observable
let prop2Values : any[] = this.myService.getResultAfterSimpleManipulation(prop1Value);
//the this.getProp3Value return observable aftet get request
return this.getProp3Value(prop2Value).pipe(
map(prop3Values =>
{
return { prop1 : prop1Value, prop2 : prop2Values, prop3 : prop3Values };
})
)
}
));
}
This should all done in a resolve function and should initiate the fullData object, by getting data from the this.gatherAllRelevantData (not happening) and without unneeded execution of the this.gatherAllRelevantData:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any>
{
const fullDataObservable = forkJoin(
{
AProp : this.myFirstSrv.getAProp(),
BProp : this.mySecondsSrv.getBProp(),
CProp : this.myThirdSrv.getCProp(),
prop1 : this.gatherAllRelevantData().map(item => items.prop1),
prop1 : this.gatherAllRelevantData().map(item => items.prop1),
prop1 : this.gatherAllRelevantData().map(item => items.prop1)
});
return fullDataObservable;
}
Upvotes: 3
Views: 959
Reputation: 15083
I would approach this problem by solving one property at a time then combining everything at the end.
AProp = this.myFirstSrv.getAProp();
BProp = this.mySecondSrv.getBProp();
CProp = this.myThirdSrv.getCProp();
prop1 = this.CProp.pipe(
mergeMap(CProp => this.propsSrv.getProp1(CProp))
)
prop2 = this.AProp.pipe(
map(AProp => this.propsSrv.getProp2(AProp))
)
prop3 = this.BProp.pipe(
mergeMap(BProp => this.propsSrv.getProp3(BProp))
)
fullData$ = forkJoin({
AProp: this.AProp,
BProp: this.BProp,
CProp: this.CProp,
prop1: this.prop1,
prop2: this.prop2,
prop3: this.prop3,
})
Upvotes: 0
Reputation: 31135
If the class fullData
is only used to hold the member variables, you could use an interface instead.
Based on the conditions you've mentioned you could use RxJS switchMap
(or mergeMap
) operator along with the map
operator to get the object of your requirement.
Try the following
export interface fullData {
AProp: any;
BProp: any;
CProp: any;
prop1: any;
prop2: any;
prop3: any;
}
const fullDataObservable: Observable<fullData> = forkJoin({ // <-- it's of type `Observable<fullData>`, not `fullData`
AProp: this.myFirstSrv.getAProp(),
BProp: this.mySecondsSrv.getBProp(),
CProp: this.myThirdSrv.getCProp()
}).pipe(
switchMap(data =>
this.someService.getProp1(data.CProp).pipe( // <-- get `prop1` that depend on `data.CProp`
map(prop1 => ({
AProp: data.AProp,
BProp: data.BProp,
CProp: data.CProp,
prop1: prop1,
prop2: this.simpleManipulate(prop1) // <-- get `prop2` that depend on `prop1`
}))
)
),
switchMap(data =>
this.someService.getProp3(data.prop2).pipe( // <-- get `prop3` that depend on `data.prop2`
map(prop3 => ({
AProp: data.AProp,
BProp: data.BProp,
CProp: data.CProp,
prop1: data.prop1,
prop2: data.prop2,
prop3: data.prop3
}))
)
)
)
return fullDataObservable;
Upvotes: 2