0

I am trying to make axios POST requests inside a for loop. However, the axios post POST request is being run n times with only the last value of the loop. Running twice with value sheetName="Virudhunagar Beds". Below is my piece of code:

const axios = require('axios')
const sheetDistrictMap = {
  "Ariyalur Beds": "5ea0abd3d43ec2250a483a4f", "Virudhunagar Beds": "5ea0abd3d43ec2250a483a58"
}
let promises = [];

for (sheetName in sheetDistrictMap) {
  promises.push(
    axios.post('https://tncovidbeds.tnega.org/api/hospitals', {
      District: sheetDistrictMap[sheetName],
      FacilityTypes: ["CHO", "CHC", "CCC"],
      IsGovernmentHospital: true,
      IsPrivateHospital: true,
      pageLimit: 100
    })
      .then(res => {
        var outputJsonArray = [];
        for (i = 0; i < res.data.result.length; i++) {
          var rowJson = {};
          var rowdata = res.data.result[i];
          rowJson["Name"] = rowdata["Name"];
          outputJsonArray.push(rowJson);
        }
        console.log("Parsed sheet: " + sheetName);
        console.log(outputJsonArray);
        console.log("========================================================");
      })
      .catch(error => {
        console.error(error)
      })
  )
}
Promise.all(promises).then(() => console.log("All data scraped"));

How do I make async calls with each loop parameter?

Vipin Verma
  • 5,330
  • 11
  • 50
  • 92
  • Here is an [article](https://dzone.com/articles/why-does-javascript-loop-only-use-last-value) about variable scope and closure in javascript loop – Sameer May 06 '21 at 10:20
  • Awesome. I was not thinking about the variable scope. I was stuck with the idea that it is caused by non-async requests. Promise was not even required. Thank you! – Vipin Verma May 06 '21 at 10:21

3 Answers3

1

Try adding const to the sheetName variable. The problem is that your variable without it behaves like var that is global in most cases. Adding a const makes the variable block-scoped so that every iteration will have a unique variable instead of using the last value that was assigned to the sheetName.

for (const sheetName of Object.keys(sheetDistrictMap)) {
  promises.push(
    axios.post('https://tncovidbeds.tnega.org/api/hospitals', {
      District: sheetDistrictMap[sheetName],
      FacilityTypes: ["CHO", "CHC", "CCC"],
      IsGovernmentHospital: true,
      IsPrivateHospital: true,
      pageLimit: 100
    })
      .then(res => {
        var outputJsonArray = [];
        for (i = 0; i < res.data.result.length; i++) {
          var rowJson = {};
          var rowdata = res.data.result[i];
          rowJson["Name"] = rowdata["Name"];
          outputJsonArray.push(rowJson);
        }
        console.log("Parsed sheet: " + sheetName);
        console.log(outputJsonArray);
        console.log("========================================================");
      })
      .catch(error => {
        console.error(error)
      })
  )
}
Ayzrian
  • 2,279
  • 1
  • 7
  • 14
1

You are hit the closure inside loops issue. You can use let and const keywords to declare the sheetName variable. Each iteration through the loop will have a new variable sheetName with loop scope.

for (let sheetName in sheetDistrictMap) {
  // the rest code
}

For more info, see JavaScript closure inside loops – simple practical example

Lin Du
  • 88,126
  • 95
  • 281
  • 483
1

I think there are two things here :

  1. let or const in the for loop which creates a global scope for the variable

  2. How you are getting data from the promises. You don't need to .then after pushing it to the array instead do this:

const axios = require('axios')
const sheetDistrictMap = {
  "Ariyalur Beds": "5ea0abd3d43ec2250a483a4f", "Virudhunagar Beds": "5ea0abd3d43ec2250a483a58"
}
let promises = [];

for (let sheetName in sheetDistrictMap) {
  promises.push(
    axios.post('https://tncovidbeds.tnega.org/api/hospitals', {
      District: sheetDistrictMap[sheetName],
      FacilityTypes: ["CHO", "CHC", "CCC"],
      IsGovernmentHospital: true,
      IsPrivateHospital: true,
      pageLimit: 100
    })
      
  )
}
Promise.all(promises).then((data) => 
   //data will array and in same sequence you hit the api
 // do the below processing for every response
   var outputJsonArray = [];
        for (i = 0; i < res.data.result.length; i++) {
          var rowJson = {};
          var rowdata = res.data.result[i];
          rowJson["Name"] = rowdata["Name"];
          outputJsonArray.push(rowJson);
        }
        //console.log("Parsed sheet: " + sheetName); // make sure you get the sheetName 
        console.log(outputJsonArray);
        console.log("========================================================");
      })
      .catch(error => {
        console.error(error)
      })
Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35