rxjs - Angular 2 Http, Observables and recursive requests -
i have rest endpoint returns list of items, max 1000 items @ time. if there more 1000 items, response has http status 206 , there's next-range
header can use in next request getting more items.
i'm working on an angular 2 application , trying implement http
, observable
. problem don't know how merge multiple observable
s depending on how many pages of items there , finally return 1 observable
component can subscribe to.
here's i've got current typescript implementation:
// note: non-working example! getallitems(): observable<any[]> { // array of items, possibly received multiple requests const allitems: any[] = []; // inner function getting range of items const getrange = (range?: string) => { const headers: headers = new headers(); if (range) { headers.set('range', range); } return this.http.get('http://api/endpoint', { headers }) .map((res: response) => { // add received items // (maybe not needed if responses can merged other way?) allitems.push.apply(allitems, res.json()); // partial content if (res.status === 206) { const nextrange = res.headers.get('next-range'); // next range of items return getrange(nextrange); } return allitems; }); }; // first range return getrange(); }
however, doesn't work. if understood correctly, observable
returned value of initial observable
, not array of items.
you can implement using expand operator. want create recursive flatmap. that's operator expand created for.
here code snippet of how works:
let times = true; // mock method http.get call const httpmock = () => { if(times) { times = false; return rx.observable.of({items: ["1", "2", "3"], next: true}); } else { return rx.observable.of({items: ["4", "5", "6"], next: false}); } } httpmock() .expand(obj => { // in case, obj response // implement logic here if 206 http header found if(obj.next) { // if have next values, call http.get method again // in example it's httpmock return httpmock(); } else { return rx.observable.empty(); } }) .map(obj => obj.items.flatmap(array => array)) .reduce((acc, x) => acc.concat(x), []); .subscribe((val) => console.log(val));
what mock first http request, has 'next' property true. matches 206 header. make second call has 'next' property false.
the result array containing results both requests. it's applicable more requests expand operator.
working jsbin example can found here: http://jsbin.com/wowituluqu/edit?js,console
edit: updated work http call returns array arrays , end result single array contains elements form arrays.
if wish have result array separate arrays request still inside, remove flatmap , return items directly. update codepen here: http://codepen.io/anon/pen/xrzyaz?editors=0010#0
Comments
Post a Comment