假设我有一个 Web 服务,它将返回基本数据,如下所示(结果名为 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'
}
}
}
}
此外,我有一个网络服务,可以返回详细的客户数据:
{
CustomerNo: 1,
Street: 'Test Street 123',
PostCode: '99999',
City: 'Blabla',
...
}
我想做的是使用 forkJoin 在 Angular4 可注入服务中组合两个服务的结果。但是当我尝试请求给定客户的每个详细信息时,我卡住了:
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);
}
如何使用forkJoin
遍历每个CustomerGroup
(flatMap曾经这样做(并获取每个Customer
的详细信息?是否可以在forkJoin
内使用forEach
?
forkJoin
的结果应如下所示:
{
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'
}
}
}
...
}
溶液
根据taras-d的描述,我错过了合并合并多个可观察量的结果的合并图。我的最终来源如下所示:
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);
}
把它们放在一起:
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;
}
最简单的方法是获取所有组和所有客户,然后将它们组合在一起。
export class AppComponent {
// Fake customer service
customerService = {
getGroups() {
return Observable.of({
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'
}
}
}
});
},
getCustomer(num) {
return Observable.of({
CustomerNo: num,
Street: `Street ${num}`,
PostCode: `PostCode ${num}`,
City: `City ${num}`
});
}
};
readAll(): Observable<any> {
// Get all groups
return this.customerService.getGroups().mergeMap(allGroups => {
const customersObservables = [];
// Loop over groups
for (let groupNum in allGroups) {
const group = allGroups[groupNum];
// Loop over customers in group
for (let customerNum in group.Customers) {
const customer = group.Customers[customerNum];
// Create observable for every group customer
customersObservables.push(
this.customerService.getCustomer(customer.CustomerNo)
);
}
}
// Join all customers observable and map (return) all groups and all customers
return Observable.forkJoin(customersObservables)
.map(allCustomers => [allGroups, allCustomers]);
});
}
ngOnInit(): void {
this.readAll().subscribe(res => {
// Here you will receive all groups and all customers
const [ allGroups, allCustomers ] = res;
console.log( JSON.stringify(allGroups, null, 2) );
console.log( JSON.stringify(allCustomers, null, 2) )
// TODO: Combine result
});
}
}