我有一个http get请求,以获取类似的数组
[
{name: 'name1', id: 1, specialProp: [] },
{name: 'name2', id: 2, specialProp: [] }
]
我需要获取每个数组项,获取一个ID,然后向服务器发送请求以获取一些信息。结果应写入属性specialProp
。之后,我需要获取道具specialProp
的数组,并为每个项目获取一些数据,然后将其放入anotherSpecialProp
中。最后,我应该拥有
[
{name: 'name1', id: 1, specialProp: [
{name: 'c', anotherSpecialProp: []},
{name: 'd', anotherSpecialProp: []}
]},
{name: 'name2', id: 2, specialProp: [
{name: 'a', anotherSpecialProp: []},
{name: 'b', anotherSpecialProp: []}
]}
]
我有代码:
this.http.get(url)
.pipe(
switchMap((mainItemArr: any) => from(mainItemArr)),
mergeMap((mainItem: any): any => {
return this.getSomeInfo(mainItem.Id) //another http get request
.pipe(
map((data: any): any => {
return Object.assign(mainItem, { specialProp: data })
}),
switchMap((mainItemArr: any): any => from(mainItemArr.specialProp)),
concatMap((item: any): any => {
return this.getSomeOtherInfo(item.Id) // one more http get request
.pipe(
map((data: any): any => Object.assign({}, task, { anotherSpecialProp: data }))
)
}),
)
})
)
因此在订阅中,我仅收到项目,而不是整个mainItemArr。 有人可以帮我解决这个问题吗?:)
答案 0 :(得分:3)
如果我做对了,您需要执行的操作如下:
getSomeInfo
并将结果(应该是数组)存储在specialProp
属性中specialProp
数组中的每个条目,您要调用getSomeOtherInfo
方法,获取更多数据并将其存储到名为anotherSpecialProp
的属性中如果这都是真的,那么您可以尝试以下方法
getArray()
.pipe(
mergeMap(mainArray => mainArray), // unwind the array received
switchMap(mainItem => getSomeInfo(mainItem.id) // fetch the first set of info from backend
.pipe(
tap(someInfo => {
mainItem['specialProp'] = someInfo; // wrote someInfo into specialProp property
}),
mergeMap(specialProps => specialProps), // unwind the array of specialProps
switchMap(specialProp => getSomeOtherInfo(specialProp.name) // for each specialProp fetch the additional data
.pipe(
tap(someOtherInfo => {
specialProp['anotherSpecialProp'] = someOtherInfo // store additional data into anotherSpecialProp property
})
)
),
toArray(), // rewind the array of specialProps and return it
map(() => mainItem)
)
),
toArray() // rewind the array of mainItems and return it
)
您可能要注意的是将mergeMap
与数组配合使用,例如mergeMap(mainArray => mainArray)
。
mergeMap
接受返回 ObservableInput 的函数作为输入。数组是一个 ObservableInput ,它在 完成 之前同步发出其所有项目。因此,传递一个将数组返回到mergeMap
的函数意味着发出该数组的所有元素。
您可以找到above example here
的示例答案 1 :(得分:2)
主要技巧是使用map
将合并范围的属性与请求结果合并。
下面是一个粗略的示例,说明如何在第一级(specialProp
)上实现这一目标:
this.http.get(url).pipe(
mergeMap(mainItemArr => {
// forkJoin will wait for each request to complete
return forkJoin(
// make a subsequent request for each item in mainItemArr
mainItemArr.map(mainItem => {
return this.getSomeInfo(mainItem.Id).pipe(
// merge getSomeInfo result with the mainItem
map(someInfo => {
return {
...mainItem,
specialProp: someInfo
};
})
)
})
)
})
)
对于anotherSpecialProp
请求-您需要更深入一层。
在现实世界的应用程序中,我建议将这些后续调用分成单独的函数/方法。
注意 :
您不需要将数组变成可观察的:
mergeMap(mainArray => mainArray)
相反,您可以将其保留在JS范围内,然后在mergeMap
中进行后续请求,例如:
mergeMap(mainArray => {
// making sub requests here
})
使用mergeMap
将数组转换为Observable也是可行的,尽管在深入1级时可能会更加混乱,恕我直言。无论如何,map
是主要技巧。
希望这会有所帮助