简体   繁体   中英

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,
        },
      })
  },
};

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.

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!");
});
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM