0

I have an array of names and would like to loop through each one of them and read a file corresponding to it with fs-extra which uses promises. How do i wait for the forEach loop to be over so i can write the results to json

Here's my current code:

const fs = require("fs-extra");
const path = require("path");
const manifest = require("../manifest.json");


manifest.forEach((element, index) => {
    const coinName = `${element.symbol.toLowerCase()}.svg`;
    let svgPath = path.join(__dirname, '..', 'svg', 'color', coinName);

    fs.readFile(svgPath, "utf8")
        .then(result => {
            const pattern = /#([A-Fa-f0-9]{6})/g
            let color = result.match(pattern)
            if (color === null) {
                manifest[index].color = undefined;
                console.log("null")
            } else {
                manifest[index].color = color;
            }
        })
        .catch(e => console.log(coinName + " NOT FOUND"))


});

fs.writeJSON("./manifest.json", manifest);
Cheeze
  • 46
  • 1
  • 8
  • 1
    See: [Wait for forEach loop to finish with async calls inside of it](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) – Mark Apr 09 '19 at 16:57

1 Answers1

0

1) change your forEach to map and return the promise.

2) Wait on all promises using Promise.all()

const fs = require("fs-extra");
const path = require("path");
const manifest = require("../manifest.json");

let promises = manifest.map((element, index) => {
  const coinName = `${element.symbol.toLowerCase()}.svg`;
  let svgPath = path.join(__dirname, '..', 'svg', 'color', coinName);

  return fs.readFile(svgPath, "utf8")
      .then(result => {
        const pattern = /#([A-Fa-f0-9]{6})/g
        let color = result.match(pattern)
        if (color === null) {
          manifest[index].color = undefined;
          console.log("null")
        } else {
          manifest[index].color = color;
        }
      })
      .catch(e => console.log(coinName + " NOT FOUND"))
});

Promise.all(promises).then(() =>
    fs.writeJSON("./manifest.json", manifest));

In case it's helpful, a simpler use case using this approach

let files = ['a', 'b', 'c', 'd', 'e', 'f'];

let promises = files.map((file, i) =>
    new Promise(resolve => setTimeout(resolve, i * 1000)));

Promise.all(promises).then(() =>
    console.log('promises all resolved, save file now', promises));
junvar
  • 11,151
  • 2
  • 30
  • 46