有一个 API( https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1 ),我想将所有数据消耗到我的 Angular 应用程序中。问题是他们的 API 有分页功能,我想一次检索所有内容。
正如您在 API 上看到的,它们的响应实际上具有指向下一页的“下一页”属性。我希望能够继续向 API 发出请求,只要“next”属性不为 null,然后将所有响应合并为一个。
我尝试过使用递归,但是当它到达第二个循环时,我得到了未定义的值。我的猜测是,这是因为异步请求,因此我得到了未定义。
下面是我的代码
@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([]);
});
}
}
然后从我刚刚调用的组件
this.GenomicsEnglandService.getPanels('https://panelapp.genomicsengland.co.uk/api/v1/panels/?page=1').subscribe(data => {
console.log(data);
})
最佳答案
虽然这个问题已经得到解答,但我想提出另一种方法,即使用 expand
运算符 [ https://rxjs-dev.firebaseapp.com/api/operators/expand] 。 expand
运算符就是为了这样的递归目的而创建的:
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);
}
查看工作 stackblitz
关于angular - 根据响应递归组合 HTTP 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56786261/