I have a REST endpoint that returns a list of items, max 1000 items at a time. If there are more than 1000 items, the response has HTTP status 206 and there\'s a Nex
Just in case someone else runs in to this. The pattern I'm using is using the same concept of expand. However this is really the 'complete' example when you need to transform the responses from the server into a different kind of Observable
like Visa Kopu's example above.
I broke out each 'step' so the flow is captured in methods (instead of writing the most compact version of it). I think it is a bit more learnable this way.
import {Injectable} from '@angular/core';
import {HttpClient, HttpParams, HttpResponse} from '@angular/common/http';
import {EMPTY, Observable} from 'rxjs';
import {expand, map} from 'rxjs/operators';
// this service is consuming a backend api that is calling/proxying a Salesforce query that is paginated
@Injectable({providedIn: 'root'})
export class ExampleAccountService {
constructor(protected http: HttpClient) {
}
// this method maps the 'pages' of AccountsResponse objects to a single Observable array of Account objects
allAccounts(): Observable {
const accounts: Account[] = [];
return this.aPageOfAccounts(null).pipe(
map((ret: HttpResponse) => {
for (const account of ret.body.accounts) {
accounts.push(account);
}
return accounts;
})
);
}
// recursively fetch pages of accounts until there are no more pages
private aPageOfAccounts(page): Observable> {
return this.fetchAccountsFromServer(page).pipe(
expand((res: HttpResponse) => {
if (res.body.nextRecordsUrl) {
return this.aPageOfAccounts(res.body.nextRecordsUrl);
} else {
return EMPTY;
}
}));
}
// this one does the actual fetch to the server
private fetchAccountsFromServer(page: string): Observable> {
const options = createRequestOption({page});
return this.http.get(`https://wherever.com/accounts/page`,
{params: options, observe: 'response'});
}
}
export class AccountsResponse {
constructor(public totalSize?: number,
public done?: boolean,
public nextRecordsUrl?: string,
public accounts?: Account[]) {
}
}
export class Account {
constructor(public id?: string,
public name?: string
) {
}
}
export const createRequestOption = (req?: any): HttpParams => {
let options: HttpParams = new HttpParams();
if (req) {
Object.keys(req).forEach((key) => {
if (key !== 'sort') {
options = options.set(key, req[key]);
}
});
if (req.sort) {
req.sort.forEach((val) => {
options = options.append('sort', val);
});
}
}
return options;
};