this.httpService.get('/user/appUser').pipe(
concatMap(users => users),
concatMap(user =>
forkJoin({
billingAddr: this.httpService
.get('/user/appUserAddr', new HttpParams()
.set('where', JSON.stringify([{ pk_addr_name: user['fk_billing_addr_name'] }]))
),
shippingAddr: this.httpService
.get('/user/appUserAddr', new HttpParams()
.set('where', JSON.stringify([{ pk_addr_name: user['fk_shipping_addr_name'] }]))
)
}).pipe(map(addr => {
user['billingAddr'] = addr.billingAddr;
user['shippingAddr'] = addr.shippingAddr;
return user;
}))
),
tap(res => console.log(res)),
toArray()
);
第一个 HTTP 请求(get '/user/appUser') 将返回一个这样的数组:
[
{user_name:'test1',fk_billing_addr_name:'addr1-1',fk_shipping_addr_name:'addr1-2'},
{user_name:'test2',fk_billing_addr_name:'addr2-1',fk_shipping_addr_name:'addr2-2'}
]
然后我将获得单独的 billingAddr 和 shippingAddr 并将其添加回用户对象本身,这是第二个 concatMap 部分。
最终输出将如下所示:
[
{user_name:'test1',fk_billing_addr_name:'addr1-1',fk_shipping_addr_name:'addr1-2',billingAddr:[...],shippingAddr:[...]},
{user_name:'test2',fk_billing_addr_name:'addr2-1',fk_shipping_addr_name:'addr2-2',billingAddr:[...],shippingAddr:[...]}
]
实际上我的代码是有效的,但奇怪的部分是第一个 concatMap(users=>users)。
如果我不把它放在那里,用户数组就不能一个一个地发送给下一个操作符。
我可以只用一个 concatMap 来简化它吗?
还有我可以简化的任何其他部分吗?
答案 0 :(得分:2)
这当然是一个有趣的问题。这是怎么回事
concatMap
按顺序发出数组的每个元素。类似于from(array)
。forkJoin
映射到 concatMap
的 observable。forkJoin
获取和分配两个新属性来调整每个元素。toArray()
运算符将末尾的所有元素/发射再次组合为一个数组并发射。我没有发现它有什么问题,除非你在等待当前用户在开始下一个之前获取它的数据。
但是,如果您希望完全并行化提取,则可以使用两个 forkJoin
。内部 forkJoin
类似于现有用法,外部 forkJoin
替换 concatMap
和 toArray
。此处的 switchMap
可以替换为任何其他映射运算符。由于 Angular HTTP 请求在第一次发出后完成,因此使用的映射运算符类型没有任何影响。
注意:这是未经测试的代码。请报告任何意外后果。
this.httpService.get('/user/appUser').pipe(
switchMap(users =>
forkJoin(users.map(user =>
forkJoin({
billingAddr: this.httpService
.get('/user/appUserAddr', new HttpParams()
.set('where', JSON.stringify([{ pk_addr_name: user['fk_billing_addr_name'] }]))
),
shippingAddr: this.httpService
.get('/user/appUserAddr', new HttpParams()
.set('where', JSON.stringify([{ pk_addr_name: user['fk_shipping_addr_name'] }]))
)
}).pipe(
map(addr => ({
...user,
billingAddr: addr.billingAddr,
shippingAddr: addr.shippingAddr
}))
)
))
)
)
通过将 concatMap
替换为 mergeMap
s