Search code examples
angularrxjsngrxangular-http

ngrx stagger load data with multiple HTTP request


I am working with an API in an Angular NGRX app that requires I make multiple calls to get all the data I'm looking for. For example, I start off by requesting a list of groups

GET http://api-path/my/groups

That returns an array of id objects, like this:

[
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyNkMmM2ZjExMS1mZmFkLTQyYTAtYjY1ZS1lZTAwNDI1NTk4YWE="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyMxNGQ2OTYyZC02ZWViLTRmNDgtODg5MC1kZTU1NDU0YmIxMzY="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyMyMGMzNDQwZC1jNjdlLTQ0MjAtOWY4MC0wZTUwYzM5NjkzZGY="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyMyYTg0OTE5Zi01OWQ4LTQ0NDEtYTk3NS0yYThjMjY0M2I3NDE="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyMzNGIwMTg1MS1jMTNkLTQ2MDQtYmIzYi01ZGUxZWNiZjAyODg="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyM1YWY2YTc2Yi00MGZjLTRiYTEtYWYyOS04ZjQ5YjA4ZTQ0ZmQ="
    },
    {
        "id": "MDJiZDlmZDYtOGY5My00NzU4LTg3YzMtMWZiNzM3NDBhMzE1IyM4NmZjZDQ5Yi02MWEyLTQ3MDEtYjc3MS01NDcyOGNkMjkxZmI="
    },
]

I then have to make a call for each id object to get the details:

GET http://api-path/group/{ID}

I'm currently using an effect to trigger these calls:

  loadGroupSuccess = createEffect(() =>
    this.actions$.pipe(
      ofType(fromActions.loadGroupSuccess),
      delay(this.debounceTime(), asyncScheduler),
      filter(({ group }) => !!team),
      mergeMap(({ group }) => [
        ...group.map((id) =>
          fromActions.loadGroupDetails({ id })
        ),
      ])
    )
  );

The loadGroupDetails action is received by another effect and makes the call out to the API. I'm currently injecting a random delay between 0-500ms with the this.debounceTime() function. If I don't put that in, all of the XHR requests happen at the same time and the browser becomes locked while the data is downloaded.

I feel like there is a better way to handle something like this. Is there a way to stagger the requests so that only a few happen at a time? Is there a better way to call out to these APIs than using effects?


Solution

  • There is a concurrency param you can set in mergeMap which can improve your performance,

    mergeMap(getHttp, 3)
    

    In this case, maximum 3 calls concurrently made at any given time