javascript: Making multiple API calls the right way
Tags: javascript, node
Published: 2021-06-06 09:34:46

Recently while reviewing a PR I realized a function was making multiple calls one by one which could have been making calls in parallel. In this post I want to share two different pieces of code (with mock) and a graph which shows how both of them progresses independently.

Let's start!!

Suppose there is a scenario where we have to make multiple calls to an API to get the full list of users, suppose there are `500` users in system, but API is capped by maximum `pageSize`, which could be let's suppose `100`. 

With above assumptions we will have to make `10` calls to get the full list of users.

Let's create a mock/fake API endpoint:
```javascript
function fakeApiCall(currentPage) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        data: {
          currentPage,
          total: 100000,
        },
      });
    }, 1000);
  });
}
```
This returns a `promise` which will be resolved after `1000ms`

>*One more use case:* Let's suppose we get a requirement to get the list of all users to process something beforehand (it could be anything, for eg: may be we just want to show the list of `active` users when admin lands on Admin Panel, to do that we will have to get all the users and then filter out the `in-active` one).

### 1. First way to solve this:

```javascript
async function oneByOneCall() {
  ...
  let currentPage = 1;

  while (currentPage <= 5) {
    let { data } = await fakeApiCall(currentPage);
    result = [...result, data];
    currentPage++;
  }
  ...
  // Do something with final result
}
```

[async/await](https://javascript.info/async-await) brings a lot of comfortability while dealing with promises, it's also very easy to write and understand code.

But, let's look at the code one more time.

So, what is happening here.
```javascript
let { data } = await fakeApiCall(currentPage);
```
Here we are saying, make the api call and wait for the result to come back, then process that result and then continue with while loop. Execution will kind of stop at this point while waiting for result to come back

huh?? That's not what we want, we wanted to process it in parallel. right?

>`NOTE:` There will be scenarios where you will have wait, could be because you are making calls to multiple APIs and you want to decide or send some data from previous response, but thats not something we are tackling here

### 2. Second way to solve this:
```javascript
async function parallelCall() {
  ...
  let start_time = new Date().getTime();
  let promises = [];
  let result = [];

  let currentPage = 1;

  while (currentPage <= 5) {
    promises.push(fakeApiCall(currentPage));
    currentPage++;
  }

  const data = await Promise.all(promises);
  data.forEach(({ data }) => {
    result = [...result, data];
  });

  ...
  // Do something with final result
}
```

So, here we are saying we will have a promise array.
```javascript
  let promises = [];
```
And in loop we are going to push each `promise` returned from `fakeApiCall` and not going to wait for result right now.
```javascript
    promises.push(fakeApiCall(currentPage));
```

When we are done with loop or collecting all the promises, we are going to wait for each of them to be finished only once.
```javascript
  const data = await Promise.all(promises);
```

And here is the graph for better representation of the execution sequence and their comparison:
### 1. Making API calls one by one, waiting for response after every call.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5ion0xmxyevtycty9en.png)

### 2. Making API calls in parallel, collecting all the promises in an array and waiting only at the end.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wktmzrlt0tzkoz6lbhkt.png)
  

So, finally, we can see we are gaining close to 4 secs (4000ms) here. That's a huge gain. So second option is much better than going with first option.

The code used in this post is available [here](https://github.com/rojha-mdsol/devto-my-examples/tree/master/async).

-- Thanks, Ravi