DEV Community

Hasin Apurbo
Hasin Apurbo

Posted on

How to make concurrent API calls in nodejs

When building the backend of a web application, we often need to call APIs of remote servers. It is not a big deal when we have to make just one or two API calls per request. But most of the time we have to make two or more API calls depending on the requests. That’s when the problem occurs. Because the more API calls you make, the longer it will need to serve the data.

Let’s assume you have to handle a request which requires five API calls. You make five API calls one by one. When all of the data is available, you clean, format, and merge them and send them to the frontend. Let’s say it takes six seconds to get data from all of the API calls. Six seconds may seem feasible but it’s always better to make things efficient and faster whenever possible.

So, to serve the request faster we can make all the API calls at once. The data from all of the API calls will come independently of each other. Once the data is available we can perform on it and serve it to the frontend. Notice, in this case, we are not waiting for each API call and then calling the next API call. We simply make all the API calls concurrent. That’s why this method is efficient and faster.

Let’s say I have to make an API that takes tags of posts as a query string and makes API calls to retrieve all the posts with those particular tags. The remote server inputs a single tag. It cannot take multiple tags as input. So, I have to make an API call per tag to retrieve all posts with the tags. I have made two versions of the same API to demonstrate that making concurrent API calls are much more efficient and faster

Code for non-concurrent API call:

app.get("/api/nonconcurrent/posts", async (req, res) => {
  let posts = [];

  // retrieve and filter all the tags from the URL
  const tags = getTags(req.query.tags);

  for(let i = 0; i < tags.length; i++) {
    const { data: newPosts } = await axios.get(
      "https://api.hatchways.io/assessment/blog/posts?tag=" + tags[i]
    );

    posts = addNewPosts(posts, newPosts.posts);
  }

  return res.send({ posts: posts });
});
Enter fullscreen mode Exit fullscreen mode

Here, an API call is made per tag and returned data is stored inside an array.

Code for concurrent API call:

app.get("/api/concurrent/posts", async (req, res) => {
  let posts = [];

  // retrieve and filter all the tags from the URL
  const tags = getTags(req.query.tags);

  // make concurrent api calls
  const requests = tags.map((tag) =>
    axios.get("https://api.hatchways.io/assessment/blog/posts?tag=" + tag)
  );

  try {
    // wait until all the api calls resolves
    const result = await Promise.all(requests);

    // posts are ready. accumulate all the posts without duplicates
    result.map((item) => {
      posts = addNewPosts(posts, item.data.posts);
    });
  } catch (err) {
    res.status(500).json({ error: String(err) });
  }

  return res.send({ posts: posts });
});
Enter fullscreen mode Exit fullscreen mode

In this case, I have called all the API calls at once. The API calls will be executed in parallel. After getting all the data from the API calls, data is sent to the frontend.

The average time taken for the non-concurrent version with two API calls takes 1.4 seconds. Whereas, it takes just 400 ms on average in the case of the concurrent version. So, on average the concurrent version is 3.5 times faster than the non-concurrent version.

The code used here is available at Github

Discussion (0)