如何使用Angular4中的Observables从后端API检索分页HTTP请求

时间:2017-10-04 19:58:11

标签: javascript angular rxjs observable

我在角度4应用程序中获得了一项服务,该应用程序从后端API检索可变数量的页面。

我在这里查看答案Angular 2 - Chaining http requests,建议使用flatMap,但这种方法不起作用,因为它要求事先知道所有请求。这在我的情况下不起作用,因为请求的数量和每个请求的URL是动态的并且是未知的。

从上一个请求的结果推断出页数/请求数。因此,如果先前的请求返回任何内容,则请求下一页以查看是否还有其他项目。

我尝试了以下

this.items = [];
_fetch(url, page) {
    this.http.get(`${url}&pageSize=2&page=${page}`).subscribe(response => {
    this.items.concat(response.json().items)
    // if the list of items is not empty fetch another page
    if (response.json().items.length > 0) {
      this._fetch(url, ++page);
    }
  });
  return Observable.of(this.items);
}

但是,在请求有机会完成之前会返回this.items,因此它总是作为空列表返回。

任何想法?

2 个答案:

答案 0 :(得分:2)

您可以使用flatMap将可观察量链接在一起

fetch(url){
    return this.http.get(`${url}/initial-api/`)
        .flatMap(res => {
            let page = res.page

            return this.get(`${url}&pageSize=2&page=${page}`);
        });
}

现在,当您订阅可观察序列时,它会将api链接在一起

这是对flatMap / mergeMap的一个很好的阅读:https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs

flatMap的优点在于它将事物保存在单个流中,而不是嵌套订阅,根据您的代码,嵌套订阅会变得非常混乱。

答案 1 :(得分:0)

由于.subscribe返回一个observable,你可以简单地链接它们。只要没有错误,它就会执行第二个错误:

this.http.get('some url').subscribe( result => {
    if (result) {
        // good to go execute second call.
        this.http.get('other url').subscribe( result2 => {
            // do something with result 1 and result 2
        })
    } else {
        // handle error. don't execute second call
    }
}, error => {
    // error occured. don't execute second call
})

您也可以在应用中设置承诺,如下所示:

firstHttpCall() {
    return new Promise( (resolve, reject) => {
        this.http.get('someurl').subscribe( result => {
            result(result);
        }, error => {
            reject(error);
        });
    });
}
secondHttpCall() {
    return new Promise( (resolve, reject) => {
        this.firstHttpCall().then( result => {
            resolve(result);
        }, error => {
            reject(error);
        });
    });
}
someOtherCall() {
    // some stuff...
    this.secondHttpCall().then( result => {
        // everything went well.
    }, error => {
        // something went wrong
    })
}

如果你可以达到你不依赖第二次通话中使用的第一个通话值的程度,我会说Promise.all也是可行的选择。