Reputation: 16512
I have a function that I want to return after 3 obersverables have complete:
initialize(){
let src1:Observable<Account>; //initialization omitted for brevity
let src2: Observable<User>; //initialization omitted for brevity
// this is one is the problem
let src3: Observable<Company[]> = this.myHttpService.getCompanies()
.pipe(
//do something that calls `this.myHttpService.getDepartments(company.id)` for each company one at a time.
);
return merge(src1, src2, src3);
}
For src3
, each company has multiple departments. I would like to make a call to this.myHttpService.getDepartments(company.id)
for each company. Only once all this.myHttpService.getDepartments
has been called for each company. Only then should src3
be complete.
Ive gone through any number of combination of concatMap
, mergeMap
....and I am just not getting it.
How do I take each company, get their departments (a Department[]
) one company at a time, and then once that is done, src3
is complete?
Upvotes: 2
Views: 1294
Reputation: 1698
There are many Ways to achieve your goal. You could use concatAll, mergeMap and toArray:
concatAll unpacks an array into individual objects, mergeMap transformes these objects into an observable emitting company's departments and toArray collects the output of the mergeMap function to ensure all departments are retrieved before the observable completes
final code could look like this:
let src3: Observable<{company: Company, departments: Department[]}[]> = this.myHttpService.getCompanies()
.pipe(
concatAll(), // use this if your getCompanies() function returns Observable<Company[]> to get a single company
mergeMap(company => this.myHttpService.getDepartments(company.id).pipe(
map(departments => ({ company, departments })))
),
toArray(), // here you receive {company: Company, departments: Department[]}[]
);
Upvotes: 0
Reputation: 17762
You may want to try something along these lines.
initialize(){
let src1:Observable<Account>; //initialization omitted for brevity
let src2: Observable<User>; //initialization omitted for brevity
// this is one is the problem
let src3: Observable<Company[]> = this.myHttpService.getCompanies().pipe(
map(companies: Array<any> => companies.map(
company => this.myHttpService.getDepartments(company.id)
)),
switchMap(getDepObsArray: Array<Observable<any>> => forkJoin(getDepObsArray))
);
return forkJoin(src1, src2, src3);
}
The idea is to use forkJoin
to ensure that
src3
returns only once all calls to the service have completedinitialize
returns an Observable which emits only when src1
src2
and src3
completeUpvotes: 1
Reputation: 9774
You can use Observable.forkJoin to achieve this.
return forkJoin([src1,src2,src3]).map(result=>{
//output as result[0], result[1], result[2]
});
Upvotes: 1