我将解释在解释问题之前使用的上下文,使用Angular和RxJS设计服务。
此模型有一个对象:
{
id: string;
title: string;
items: number[];
}
我通过GET /element/:id
获得了这种类型的每个对象(称为“元素”)
每个元素都有一个items: number[]
,其中包含一个数字数组,每个数字都有一个URL,因此我为每个数字执行新的GET /element/:id/:itemNumber
,并返回项目详细信息。该项目的详细信息模型如下:
{
idItem: string;
title: string;
}
因此,在我的服务中,我想为组件提供一个方法,该方法将返回一个Observable,它将获得一个对象数组,其中每个对象都具有带有一个加法属性的元素模型,该模型将包含其详细信息的数组。项目。所以,我将展示我拥有的东西:
服务:
getElement(id: string): any {
return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
map(element => this.getAllItemsDetail(element))
}
getAllItemsDetail(element: Element): any {
return of(...element.items).pipe(
map(val => this.getItemDetail(element.id, val)),
concatAll()
);
}
我的问题是,在map(element => this.getAllItemsDetail(element))
方法中的getElement
之后,我不理解如何在RxJS中合并它返回的items数组和在具有元素对象的地图。我需要在该映射后添加“任何内容”以计算Object.Assign以合并两个对象。
编辑
使用@ chiril.sarajiu的答案,他给了我一个线索,利用switchMap
我可以映射可观察对象(map
用于对象,“对结果对象进行计算”)。因此,我的代码不是我所知道的最漂亮的版本...,我将尝试使用它,但是它可以工作。因此,最终代码如下所示:
getElement(id: string): any {
return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
switchMap(element => this.getAllItemsDetail(element)),
map(result => { return Object.assign({}, result.element, {itemsDetail: result.items})})
);
}
getAllItemsDetail(element: Element): any {
const results$ = [];
for (let i = 0; i < element.items.length; i++) {
results$.push(this.getItemDetail(element.id, element.items[i]));
}
return zip(...results$).pipe(
map(items => { return Object.assign({}, { element, items })})
);
}
请注意,如果result $为空,则有关zip不会发出值的可能性,在这种情况下,您可以将of(未定义)添加到result $数组中,并考虑到项目将为[undefined]
答案 0 :(得分:1)
要映射另一个可观察对象,您应该使用switchMap
函数而不是map
所以
getElement(id: string): any {
return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
switchMap(element => this.getAllItemsDetail(element))
}
更新