Serial Vs. Parallel API calling in JavaScript
Tags: webdev, javascript, react, node
Published: 2023-08-29 05:40:41

Most of the times, we have to call API to create, read, update or delete (CRUD) the resource on some server (in layman terms).

I am saying API, but what I am talking about is `performing any asynchronous task` in serial or parallel manner.

Before moving forward, you should be aware of [Promise](https://dev.to/shameel/understanding-promise-in-javascript-45kc) and methods like Promise.all() and Promise.allSettled() as they will be used to demonstrate the examples.

You can get the code used in this example from [here](https://github.com/Shameel123/serial-and-concurrent-api-calls-js/blob/main/serialParallel.js) for you to try it out yourself.

## Serial API Calling

Lets make a function for a fake API call:

```js
function fakeAPICall(id, delay) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (typeof id === 'number') {
                resolve(`Response from API call ${id}`);
            } else {
                reject(`Provide id number in API call}`);
            }
        }, delay);
    });
}
```

For serial calling, we can use this function:

```js
async function serialExecution() {
    console.time('serialExecution')
    try {
        const response1 = await fakeAPICall(1, 1000);
        console.log(response1);

        const response2 = await fakeAPICall(2, 1500);
        console.log(response2);

        const response3 = await fakeAPICall(3, 1200);
        console.log(response3);
    } catch (error) {
        console.error(error);
    }
    console.timeEnd('serialExecution')
}
serialExecution();
```
When I executed it, I got this response:
```
Response from API call 1
Response from API call 2
Response from API call 3
serialExecution: 3.739s
```

As you can see that each API was called one by one and the total execution (on my system) was completed in `3.739 seconds`.

## Parallel API Calling

In order to call APIs in parallel manner, you have to use `promise.all()` or `promise.allSettled()` method as per your use-case.
You should use `promise.all()` if you want to make sure to receive the result of all promises whereas, you should use `promise.allSettled()` if you want to receive the result of all the APIs whether they return response or error out. For more details of how promise methods work, their differences and use-cases, [please read this](https://dev.to/shameel/javascript-promise-all-vs-allsettled-and-race-vs-any-3foj).

Now... Let's dive into the code:

```js
async function parallelExecution() {
    console.time('parallelExecution')

    try {
        const promises = [
            fakeAPICall(1, 1000),
            fakeAPICall(2, 1500),
            fakeAPICall(3, 1200)
        ];

        const responses = await Promise.all(promises);
        // const responses = await Promise.allSettled(promises);
        console.log(responses);
    } catch (error) {
        console.error(error);
    }
    console.timeEnd('parallelExecution')
}
parallelExecution();
```

When I executed it, I got this response:

```
[
  'Response from API call 1',
  'Response from API call 2',
  'Response from API call 3'
]
parallelExecution: 1.514s

```

As you can see that result was received `1.514 seconds`, all at once.

_Please note that, the result from this process is as slow as the slowest response from any of the API._

For example:
- API 1 takes 1 second.
- API 2 takes 2 seconds.
- API 3 takes 3 seconds.

Then the response will be returned after 3 seconds when the slowest API response has returned.

You can try this code for `allSettled()` as well.

## Is it really parallel?

The answer is no. The requests are sent in concurrent manner, not in parallel manner.

Parallel Execution means that the three API should be executed by three threads in parallel manner.
**BUT**
We know that JavaScript is single-threaded and with the use of event-loop, it gives us an illusion of parallelism but in reality, it's a concurrent behavior.

However, there are ways to achieve parallel behavior using techniques like Web Workers and child processes in Node.js but we will get down to them in our future blogs =)

## Conclusion

In this blog we learned calling APIs or performing asynchronous operations in sequential manner as well as in concurrent (not parallel) manner.

I hope you learned something from this :-)

Follow me for more such content:
LinkedIn: https://www.linkedin.com/in/shameeluddin/
Github: https://github.com/Shameel123