根据响应递归组合HTTP结果 [英] Recursively combining HTTP results based on response

查看:88
本文介绍了根据响应递归组合HTTP结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个API( https://panelapp.genomicsengland. co.uk/api/v1/panels/?page=1 ),我想将所有数据消耗到我的角度应用程序中.问题在于他们的API具有分页功能,我想一次检索所有内容.

如您在API上所见,它们实际上在响应中具有指向下一页的"next"属性.我希望只要"next"属性不为null,就可以继续向API发出请求,然后将其所有响应合并为一个.

我尝试使用递归,但是当它到达第二个循环时,我得到了不确定的值.我的猜测是,这是因为异步请求,因此我未定义.

下面是我的代码

@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运算符[

查看正在运行的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆