我正在尝试根据前一个请求发出多个 http 请求,并将返回的数据组合到最终结果对象。
我有两个端点:
/properties
它返回给我类似的东西:{ "data":[ { "id":1, "name":"Property 1", "units":[ { "id":1, "name":"Property 1 - Unit 1", }, { "id":2, "name":"Property 1 - Unit 2", }, ], }, { "id":2, "name":"Property 2", "units":[ { "id":3, "name":"Property 2 - Unit 3", } ] } ] }```
/properties/${property.id}/units/${unit.id}/bookings
它返回我一些与先前请求相关的对象,例如:{ "data": { "id": 1 }, "meta": { "count": 5 } }
我想要实现的是将这两个响应在单个单元级别上合并为一个。 像这样:
{
[
...
{
"id":2,
"name":"Property 2",
"units":[
{
"id":3,
"name":"Property 2 - Unit 3",
"bookings_meta": {
"count":5
}
}
]
}
]
}
我创建了这样的东西,它工作正常:
list(): Observable<any> {
return this.http.get('/properties').pipe(
map((results: any) => results.data),
flatMap((properties: any[]) => {
if (properties.length > 0) {
return forkJoin(properties.map((property: any) => {
return forkJoin(property.units.map((unit: any) => {
return this.http.get(`/properties/${property.id}/units/${unit.id}/bookings`).pipe(
map(({ meta }) => {
unit.bookings_meta = meta
return unit;
})
)
}))
}))
}
return of([]);
})
);
}
this.list().subscribe(response => {
console.log(response)
})
但我认为这不是 100% 正确的解决方案。
我感觉有太多的 forkJoin
,也许它不应该出现在 flatMap
中?
单位之间的预订请求应该是独立的。
有人知道如何改进上面的代码吗?
最佳答案
forkJoin
会在所有调用完成后返回数据并返回结果
const combined = Observable.forkJoin(
this.http.get('https:// ...properties').map((res: Response) => res.json()),
this.http.get('https:// ..properties/${property.id}/units/${unit.id}/bookings')
.map((res: Response) => res.json())
)
combined.subscribe(latestValues => {
console.log( "latestValues" , latestValues );
});
更新:
可以使用 flatMap
运算符将一个 Observable 发出的项转换为另一个 Observable。它创建一个内部 Observable
并将其结果平铺到外部流。
list(): Observable<any> {
return this.http.get('/properties')
.flatMap(properties => properties.map(p => p.units.map(unit =>
{
this.http.get(`/properties/${property.id}/units/${unit.id}/bookings`)
})))
.subscribe(res => { // some actions });
}
关于javascript - Angular 8 + RxJS 以及合并 flatMap 和 forkJoin 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59531241/