我有一个REST API接口,它只能获得一些信息的第一级。
所以例如我想收集小组。每个小组都可以有子组。例如"第1组"有子组" A组"和" B组"。 " A组"有子组" GroupX"。等等。
但API只为我提供了组名的第一级组。所以我通过"第1组"到API并返回" A组"和" B组"。要获得A组的supgroup,我需要再次调用API。但我不知道它会有多少次迭代。
所以我考虑使用递归,但我还没有走远。
到目前为止我的代码:
getGroupChildren(group:string){ return this restService.getGroupChildren(group)}
getGroups():Promise<any>{
let collection:string[] = [];
return this.getGroupChildren("Group A").then((result)=> {
if(result.data.length !==0){
return this.getGroupChildren(data[0].groupName);
}
});
}
现在这只会让我回到第一个元素的第一个Supgroups。
如何完成它总能找到每个Supgroup,无论多少?使用Observables也许好吗?
这是一个API调用的示例结构:
{ "groupName" : "Group_1", "children" : ["Group_A", "Group_B"]}
答案 0 :(得分:3)
您可以使用flatMap
Observable
运算符实现您的目标
getGroups(group: string) {
return this.http.get(`/group/{group}`).flatMap(response => {
if (response.children.length === 0) { // you hit a leaf, stop recursion here
return Observable.of(response);
} else { // there are more levels to go deeper
return this.getGroups(response.children[0].groupName);
}
});
}
修改使用承诺
假设您使用GroupService
来返回数据而不是HttpClient
。您可以使用Promise
运算符将Observable
转换为fromPromise
。
getGroups(group: string) {
return Observable.fromPromise(this.groupService.get(group)).flatMap(response => {
if (response.children.length === 0) { // you hit a leaf, stop recursion here
return Observable.of(response);
} else { // there are more levels to go deeper
return this.getGroups(response.children[0].groupName);
}
});
}
编辑2 使用此服务
我们来看看你的例子。你有以下json
{
"groupName": "Group_1",
"children" : ["Group_A", "Group_B"]
}
在您的组件文件中,您按如下方式调用服务
...
this.recursiveGroupService.getGroups("Group_1")
.subscribe(response => {
// at this point response will be `Group_A`
})
编辑3 获取整个对象
这一次,我们将使用forkJoin
并为所有孩子调用getGroups
,并在children
数组中收集结果。
注意:我自己没有测试过此代码。它可能包含一些错误。如果有,请告诉我。
import { forkJoin, of } from 'rxjs';
import { map } from 'rxjs/operators';
getGroups(group: string) {
let retVal;
return Observable.fromPromise(this.groupService.get(group)).flatMap(response => {
retVal = {
groupName: response.groupName
};
if (response.children.length === 0) { // you hit a leaf, stop recursion here
return of(retVal);
} else { // there are more levels to go deeper
// this will create list of observable for each child
const children$ = response.children.map(
child => this.getGroups(child));
// forkJoin will execute these observables in parallel
return forkJoin(children$).pipe(
map(results => {
// results is an array containing children data
retVal.children = results;
return retVal;
})
);
}
});
}
答案 1 :(得分:1)
您可以使用Promise.all
递归解析更深层次的子项,然后使用结果(数组)创建一个对象来解析承诺:
getGroups(groupName = "Group A") {
return this.getGroupChildren(groupName).then((result) =>
Promise.all(result.data.map( ({groupName}) => this.getGroups(groupName) ))
).then(children => ({ groupName, children }));
}
所以承诺的价值可能是这样的:
[{
groupName: "Group A",
children: [{
groupName: "Group A1",
children: []
}, {
groupName: "Group A2",
children: []
}]
}]