Let's say I've got a web service that will return basic data as follows (result is named CustomerGroups):
{
0: {
Name: 'Group 1',
Customers: {
0: {
CustomerNo: 1,
Name: 'Customer 1'
},
1: {
CustomerNo: 2,
Name: 'Customer 2'
}
}
},
1: {
Name: 'Group 2',
Customers: {
0: {
CustomerNo: 3,
Name: 'Customer 3'
},
1: {
CustomerNo: 4,
Name: 'Customer 4'
}
}
}
}
Furthermore i've got a web-service that will return detailed customer data:
{
CustomerNo: 1,
Street: 'Test Street 123',
PostCode: '99999',
City: 'Blabla',
...
}
What I want to do is to combine the result of both services using a forkJoin in an Angular4 injectable service. But I stuck when I try to request each detailed information on a given customer:
ReadAll(useCache?: boolean): Observable<ICustomerGroup[]> {
if (!this.customerGroupCache || !useCache) {
return this.http.get(this.urlGetAll)
.map((res: Response) => res.json())
.flatMap((customerGroups: any[]) => {
if (customerGroups.length > 0) {
return Observable.forkJoin(
customerGroups.map((customerGroup: any) => {
return this.customerService.get(/* any CustomerNo of customerGroup.Customers */)
// ^---- This is my problem!!!
})
);
}
// No data! Return empty array
return Observable.of([]);
})
.catch((error: any) => Observable.throw(error.message || 'Server error'));
}
return Observable.of(this.customerGroupCache);
}
How can I use the forkJoin to loop over each CustomerGroup (flatMap used to do that) and get the detailed information for each Customer? Is it possible to use forEach inside a forkJoin?
The result of forkJoin should look like:
{
0: {
Name: 'Group 1',
Customers: {
0: {
CustomerNo: 1,
Name: 'Customer 1',
Street: 'Test Street 123',
PostCode: '99999',
City: 'Blabla'
},
1: {
CustomerNo: 2,
Name: 'Customer 2',
Street: 'Test Street 456',
PostCode: '888',
City: 'Blabla'
}
}
}
...
}
Solution
As per description by taras-d, I missed mergeMap to combine the results of multiple Observables. My final source looks like:
ReadAll(useCache?: boolean): Observable<ICustomerGroup[]> {
if (!this.customerGroupCache || !useCache) {
return this.http.get(this.urlGetAll)
.mergeMap((res: Response) => {
const customerObservables = [];
let groups = res.json();
groups.forEach((group, i) => {
group.Customers.forEach((cust, j) => {
customerObservables.push(this.customerService.get(cust.CustomerNo));
});
});
return Observable.forkJoin(customerObservables)
.map(customers => {
this.customerGroupCache = this.buildCustomerGroupArray(groups, customers);
return this.customerGroupCache;
});
});
}
return Observable.of(this.customerGroupCache);
}
Put it all together:
private buildCustomerGroupArray(allGroups: any, allCustomers: any): Array<ICustomerGroup> {
let result: Array<ICustomerGroup> = Array<ICustomerGroup>();
allGroups.forEach((group, index) => {
let newGroup = new CustomerGroup();
newGroup.ActionFlag = ActionType.Undefined;
newGroup.Name = group.Name;
newGroup.OldName = group.OldName;
newGroup.CustomerList = Array<ICustomerGroupItem>();
group.Customers.forEach((cust, index2) => {
if (allCustomers.find(p => p.CustomerNo === cust.CustomerNo)) {
let currCust = allCustomers.find(p => p.CustomerNo === cust.CustomerNo);
let newGroupItem: ICustomerGroupItem = new CustomerGroupItem({
ActionFlag: ActionType.Undefined,
CustomerName: currCust.Name,
CustomerNo: currCust.CustomerNo
});
newGroup.CustomerList.push(newGroupItem);
}
});
result.push(newGroup);
});
return result;
}