neptunian
neptunian

Reputation: 410

How to make multiple Ajax request in RxJS based on first response

I'm using a redux-observable epic to fetch repos from a particular organization on GitHub using the search endpoint. My main issue is i need to sort by "watchers" so I need ALL the repos, but GitHub only allows one to return at most 100 per page. The response includes "total_count" which I can use to figure out how many more requests I need to make (# of pages). Here is my code so far:

export const fetchRepos = actions$ =>
  actions$.pipe(
    ofType(FETCH_REPOS),
    switchMap(action =>
      ajax.getJSON(`https://api.github.com/search/repositories?q=org:${action.payload.orgName}&per_page=100`).pipe(
        flatMap((response) => ([setRepos(response.items), setCurrentOrg(action.payload.orgName), fetchReposSuccess(response.item)])),
        catchError(error => of(fetchReposFailed()))
      )   
    )   
  ); 

I'm wondering how I use the "total_count" prop of the first response to make more ajax requests based on that number and merge into one stream without changing my code too much.

Upvotes: 2

Views: 962

Answers (1)

martin
martin

Reputation: 96889

I think the easiest way is to use the expand() operator that recursively projects the response from the Ajax call where you can decide if there're more pages you need to grab. Therefore, you don't even need to use total_count because you can simply keep downloading pages until you get less items than your per_page param:

This is for example how I can grab all repositories from my account:

const PER_PAGE = 10;
const API_URL = 'https://api.github.com/search/repositories';

const makeAjax = page => ajax.getJSON(`${API_URL}?q=org:martinsik&per_page=${PER_PAGE}&page=${page}`).pipe(
  map(response => ([page, response])),
);

makeAjax(1)
  .pipe(
    expand(([page, response]) => response.items.length < PER_PAGE
      ? empty()
      : makeAjax(page + 1)
    ),
    map(([page, response]) => response),
    toArray(),
  )
  .subscribe(console.log);

See live demo: https://stackblitz.com/edit/rxjs6-demo-kccdwz?file=index.ts

Upvotes: 3

Related Questions