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 observables 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

Popular posts from this blog

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -