1
\$\begingroup\$

Here's what I trying to do:

Given a paginated API, get all the resources using parallel requests.

The API returns a limited number of resources per call. So, you need to use an offset parameter to get to the next set of data until all data is extracted.

Here's my idea (but getting some warning because I'm using flat on the response), so maybe there's a better way to do this.

  1. Get the total count of items.
  2. Given the count and the limit, calculate how many requests are needed to get all data.
  3. Trigger all requests in parallel and combine all data into a flattened array.

Here's an example:

https://stackblitz.com/edit/paginated-api?embed=1&file=index.ts&hideExplorer=1&devtoolsheight=100

getCount().pipe(
  mergeMap(count => range(0, Math.ceil(count / limit))),
  map(offset => getDevices(offset, limit)),
  combineAll(),
).subscribe(res => {
  const a = res.flat(); // <--- warning: Property 'flat' does not exist on type '{ name: string; }[][]'.
  console.log(JSON.stringify(a));
});

I feel this solution is a little hacky. It's flattening the response in the subscription. I'd like to know if there's an RXJS operator that I can use on the pipe to flatten the response, so I don't have to in the subscription?

How to merge the multiple observables responses into a single array?

\$\endgroup\$
1
\$\begingroup\$

Use mergeMap on the call to getDevices, then mergeAll to flatten the results, and toArray to convert back to an array:

getCount().pipe(
  mergeMap(count => range(0, Math.ceil(count / pageSize))),
  mergeMap(offset => getDevices(offset, pageSize)),
  mergeAll(),
  toArray()
).subscribe(res => {
  console.log(JSON.stringify(res));
});

See here: https://stackblitz.com/edit/so-rxjs-merge-results?file=index.ts

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.