Reputation: 34475
I am trying to use forkJoin
to get the results of several observables (http requests in real code) together.
One of the source observable (mainObs
below) has a map
operator applied so that the output has the same format as the other observables.
My problem is that in the forkJoin
subscribe, the first result is an observable, and not the output of the first observable.
Here is a sample code, with a stackblitz demo.
Am I missing something?
import { forkJoin, Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
let mainObs = of("main").pipe(map(res => of({success: true, result: res})));
let listOfObservables: Observable<any>[] = [mainObs];
listOfObservables.push(createObs());
listOfObservables.push(createObs());
forkJoin(listOfObservables).subscribe((res: any[]) => {
console.log(res);
//Problem: res[0] is an Observable, not a value
console.log(res[0].success);// <==error
});
function createObs()
{
return of({success: true, result: "dummy"})
}
Upvotes: 1
Views: 10044
Reputation: 8062
1: map
of("main").pipe(
map(res => of({success: true, result: res}))
);
This takes the string "main" and then maps that string to an observable. That observable is emitted. What that observable does doesn't matter here as it's never subscribed to.
2: mergeMap
of("main").pipe(
mergeMap(res => of({success: true, result: res}))
);
This takes the string "main" and then maps that string to an observable. The returned observable is subscribed to and its emissions are passed forward. Finally, {success: true, result: "main"}
is emitted.
3: Back to map
of("main").pipe(
map(res => ({success: true, result: res}))
);
This takes the string "main" and maps it to the object {success: true, result: "main"}
. Then that object is emitted.
#2 and #3 have the same final output in these examples. As with most tasks, there is generally more than one way to achieve the same result. #3 is the most performant in this case as you avoid creating an observable and managing it with mergeMap.
Upvotes: 1
Reputation: 5944
of
creates a new observable. So your mainObs
return a new observable when it returns.
You probably meant to return the actual result:
import { forkJoin, Observable, of } from "rxjs";
import { map } from "rxjs/operators";
let mainObs = of("main").pipe(map(res => ({ success: true, result: res })));
// creating a typed array helps preventing this problem early.
let listOfObservables: Observable<{ success: boolean; result: string }>[] = [
mainObs
];
listOfObservables.push(createObs());
listOfObservables.push(createObs());
forkJoin(listOfObservables).subscribe(
(res: { success: boolean; result: string }[]) => {
console.log(res);
console.log(res[0].success); // <== ok
}
);
function createObs() {
return of({ success: true, result: "dummy" });
}
Upvotes: 1