Leomar de Souza
Leomar de Souza

Reputation: 757

Execute block of code only after loop with requests from axios is finished

I have a script that reads an excel file and gets data from a specific column to perform a search on the Google Maps API where I use axios. For each request made, I need to save it in the newFileList variable. After completing all the requests, I must save the contents of this variable in a file. However, whenever I run my code, the file is being saved without the content of the newFileList variable. How do I wait for all requests to finish before being able to save the content in the file?

Note: the reading, writing and requesting data are working. I just need the rescue to happen only after all the loop requests are finished. I tried to solve by placing the loop inside a promisse and at the end of the execution of this loop I used resolve.

const xlsx = require("node-xlsx");
const fs = require("fs");
const coordinate = require("./coordinate");

const resourcePath = `${__dirname}/resources`;
const contentFile = xlsx.parse(`${resourcePath}/file-2.xlsx`)[0].data;
const newFile = [[...contentFile, ...["Latitude", "Longitude"]]];

for (let i = 1; i < contentFile.length; i++) {
  const data = contentFile[i];
  const address = data[2];
  coordinate
    .loadCoordinates(address)
    .then((response) => {
      const { lat, lng } = response.data.results[0].geometry.location;
      newFile.push([...data, ...[lat.toString(), lng.toString()]]);
    })
    .catch((err) => {
      console.log(err);
    });
}

console.log(newFile);

//The code below should only be executed when the previous loop ends completely

var buffer = xlsx.build([{ name: "mySheetName", data: newFile }]); // Returns a buffer
fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
  if (err) {
    return console.log(err);
  }
  console.log("The file was saved!");
});

The coordinate file:

const axios = require("axios");

module.exports = {
  loadCoordinates(address) {
    const key = "abc";
    return axios
      .get(`https://maps.googleapis.com/maps/api/geocode/json`, {
        params: {
          address,
          key,
        },
      })
  },
};

Upvotes: 0

Views: 691

Answers (2)

Sai Raman Kilambi
Sai Raman Kilambi

Reputation: 888

You need to use Promise.all() to wait until all the promises are resolved. After that execute the writeToFile part. For more info on Promise.all(), you can refer https://www.javascripttutorial.net/es6/javascript-promise-all/

const requestPromiseArray = [];

for (let i = 1; i < contentFile.length; i++) {
  const data = contentFile[i];
  const address = data[2];
  requestPromiseArray.push(coordinate
    .loadCoordinates(address))
}

Promise.all(requestPromiseaArray).then(results=>{
     // Handle "results" which contains the resolved values.
      // Implement logic to write them onto a file
    var buffer = xlsx.build([{ name: "mySheetName", data: results }]);
    fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
      if (err) {
         return console.log(err);
       }
     console.log("The file was saved!");
});
})

Upvotes: 1

Andrei
Andrei

Reputation: 410

Will using an async IIFE help?

const xlsx = require("node-xlsx");
const fs = require("fs");
const coordinate = require("./coordinate");

const resourcePath = `${__dirname}/resources`;
const contentFile = xlsx.parse(`${resourcePath}/file-2.xlsx`)[0].data;
const newFile = [[...contentFile, ...["Latitude", "Longitude"]]];

(async() => {
    try{
        for (let i = 1; i < contentFile.length; i++) {
          const data = contentFile[i];
          const address = data[2];
          await coordinate
            .loadCoordinates(address)
            .then((response) => {
              const { lat, lng } = response.data.results[0].geometry.location;
              newFile.push([...data, ...[lat.toString(), lng.toString()]]);
            })
            .catch((err) => {
              console.log(err);
            });
        }

        console.log(newFile);

        //The code below should only be executed when the previous loop ends completely

        var buffer = xlsx.build([{ name: "mySheetName", data: newFile }]); // Returns a buffer
        fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
          if (err) {
            return console.log(err);
          }
          console.log("The file was saved!");
        });
    } catch(e) {
        console.log(e)
    }
})();

Do note that I added await before coordinate.loadCoordinates, in order to make sure the first axios request is finished before we proceed to the next one.

Upvotes: 1

Related Questions