Search code examples
javascriptnode.jsasync-awaitaxioses6-promise

How to make multiple API calls with a delay between each in Node.js


My goal was to make multiple api calls for a list of data. Lets say I had the following code

const  axios = require('axios');

const  axiosRequests = [];
const strings = ['a', 'b', 'c'];
for (let  str  of  strings) {
    axiosRequests.push(axios.get(`https://www.apiexample.com/get/?cfg=json&value=${str}`))
}

The easiest solutions was to apply the following:

let  responseArray;
try {
    responseArray = await  Promise.all(axiosRequests);
} catch (err) {
    console.log(err);
}

responseArray.map(response  => {
    //make something with the response
{

But the problem I encountered with from the API was the HTTP 429 Too Many Requests response status code, which means that the API restricts the number of requests for a period of time.

I want to add a delay between each request.

How can I do this?


Solution

  • You can call in series. However, I recommend using chunks, to make it more useful.

    Using chunk, best performance:

    const delay = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
    
    const getInChunk = async function (items, chunkSize) {
      let results = [];
      let chunkPromises = [];
      let chunkResults = [];
      for (let index = 0; index < items.length; index++) {
        if (index % chunkPromises === 0) {
          chunkPromises = [];
          chunkResults.push(await Promise.all(chunkPromises));
        } else {
          chunkPromises.push(
            axios.get(`https://jsonplaceholder.typicode.com/todos/${items[index]}`).then(res => res.data)
          );
        }
      }
      // last chunk
      if (chunkPromises.length) {
        chunkResults.push(await Promise.all(chunkPromises));
      }
      // flatten 
      chunkResults.forEach(chunk =>{
        results = results.concat(chunk)
      })
      console.log(results)
      return results;
    };
    
    async function main() {
      const strings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      const results = await getInChunk(strings, 5);
      console.log(results);
    }
    main();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

    Simple:

    const axios = require("axios");
    const delay = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
    const getInSeries = async (promises) => {
      let results = [];
      for (let promise of promises) {
        results.push(await delay().then(() => promise));
      }
      return results;
    };
    const getInParallel = async (promises) => Promise.all(promises);
    async function main() {
      const strings = [1, 2, 3, 4];
      const promises = strings.map((id) =>
        axios
          .get(`https://jsonplaceholder.typicode.com/todos/${id}`)
          .then((res) => res.data)
      );
      const results = await getInSeries(promises);
      console.log(results);
    }
    main();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

    Performance friendly series. loop one time O(N).

    const delay = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
    const getTodosSeries = async function (items) {
      let results = [];
      for (let index = 0; index < items.length; index++) {
        await delay();
        const res = await axios.get(
          `https://jsonplaceholder.typicode.com/todos/${items[index]}`
        );
        results.push(res.data);
      }
      return results;
    };
    
    async function main() {
      const strings = [1, 2, 3, 4];
      const results = await getTodosSeries(strings);
      console.log(results);
    }
    main();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>