基于响应递归组合HTTP结果 [英] Recursively combining HTTP results based on response
问题描述
有一个 API(https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1) 我想将所有数据消耗到我的 angular 应用程序中.问题是他们的 API 有分页,我想一次检索所有内容.
正如您在 API 上看到的,他们的响应中实际上有next"属性,指向下一页.只要next"属性不为空,我就希望能够继续从 API 请求,然后将所有响应合并为一个.
我尝试使用递归,但是当它到达第二个循环时,我得到了未定义的值.我的猜测是因为异步请求,因此我未定义.
下面是我的代码
@Injectable()导出类 GenomicsEnglandService {面板 = [];构造函数(私有 http:HttpClient){}getPanels(url): Observable{const 标头 = 新的 HttpHeaders().append('内容类型', '应用程序/json').append('接受', '*/*');返回 this.http.get(url, {headers: headers}).map((数据) => {面板 = panel.concat(data.results);如果(数据.下一个){this.getPanels(data.next);}别的{返回面板;}}).catch((e) => {Raven.captureMessage("GENOMICS ENGLAND ERROR:" + JSON.stringify(e));返回([]);});}}
然后从我的组件中调用
this.GenomicsEnglandService.getPanels('https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1').subscribe(data => {控制台日志(数据);})
虽然这个问题已经得到解答,但我还是想提出另一种方法,通过使用 expand
运算符 [https://rxjs-dev.firebaseapp.com/api/operators/expand].expand
运算符就是为了这样的递归目的:
getResult() {const url = "https://panelapp.genomicsengland.co.uk/api/v1/panels/";返回 this.getResponse(url).管道(expand((res: any) => this.getResponse(res.next)),takeWhile((res: any) => res.next, true),concatMap((res: any) => res.results),减少((acc,val)=> {acc.push(val);返回acc;}, []),点击(_ => {控制台日志(_);this.loading = false;}))}获取响应(网址){返回 this.httpClient.get(url);}
参见工作 stackblitz>
There's an API(https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1) that I want to consume all the data to my angular apps. The problem is that their API have pagination, and I want to retrieve all of the content at once.
As you can see on the API, they actually have "next" attribute on their response which point to the next page. I want to be able to keep requesting from the API as long as "next" attribute is not null then combine all their response into one.
I have tried using recursive, but by the time it reach the 2nd loop I get undefined value. My guess is that its because async request, hence I get undefined.
Below is my code
@Injectable()
export class GenomicsEnglandService {
panels = [];
constructor(private http: HttpClient) {
}
getPanels(url): Observable<any>{
const headers = new HttpHeaders()
.append('Content-Type', 'application/json')
.append('Accept', '*/*');
return this.http.get(url, {headers: headers})
.map((data) => {
panels = panels.concat(data.results);
if(data.next){
this.getPanels(data.next);
}else{
return panels;
}
})
.catch((e) => {
Raven.captureMessage("GENOMICS ENGLAND ERROR: " + JSON.stringify(e));
return of([]);
});
}
}
Then from my component I just called
this.GenomicsEnglandService.getPanels('https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1').subscribe(data => {
console.log(data);
})
Although this question has been answered, I would like to propose another approach by using expand
operator [https://rxjs-dev.firebaseapp.com/api/operators/expand]. expand
operator is made for such recursive purposes:
getResult() {
const url = "https://panelapp.genomicsengland.co.uk/api/v1/panels/";
return this.getResponse(url)
.pipe(
expand((res: any) => this.getResponse(res.next)),
takeWhile((res: any) => res.next, true),
concatMap((res: any) => res.results),
reduce((acc, val) => {
acc.push(val);
return acc;
}, []),
tap(_ => {
console.log(_);
this.loading = false;
})
)
}
getResponse(url) {
return this.httpClient.get(url);
}
See working stackblitz
这篇关于基于响应递归组合HTTP结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!