I am calling an external API from an angular2 app, which provides data in paginated form. The response looks like this
{
next: "next_url",
results: []
}
Can I use Rxjs or inbuilt Http class of Angular2, which returns an observable, to concat the results from next url, till
{
next: null,
results: []
}
I feel I need to user concatMap operator, but I have not figured out the syntax as I am new to Reactive Extentions.
Here is how I would do it:
import {Component} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
@Component({
selector: 'my-app',
template: `<h2>Results: {{out | async | json}}</h2>`,
})
export class App {
constructor() {
this.out = this.getAllResults();
}
getAllResults(startIdx = 0) {
return this.getData(startIdx)
.concatMap(data => {
if (data.next) {
return this.getAllResults(data.next)
.map(resultsToJoin => [...data.results, ...resultsToJoin]);
} else {
return Observable.of(data.results);
}
});
}
// pretend this is our http call
getData(idx : number) {
const data = [{
next: 1,
results: [1, 2]
}, {
next: 2,
results: [3, 4]
}, {
next: null,
results: [5, 6]
}];
return Observable.of(data[idx]);
}
}
http://plnkr.co/edit/7r4TaW
Just of sake of an alternative solution this one also works
getAllResults(startIdx = 0) {
return this.getData(startIdx)
.expand(data => {
return data.next ? this.getData(data.next) : Observable.empty()
}).scan((acc, data) => {
return [...acc, ...data.results]
}, []);
}
expand operator recursively call the inner observable. Without scan operator, it would keep emitting data of each page. Use scan to reduce the data of each page into single array of results.
Note: This is not exactly the solution I was looking for. Because it emits each page results as array, and not just the final array. But was interesting to discover these useful operators.
http://plnkr.co/edit/vrZEywkeys6sa5Nsccbg?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With