javascriptnode.jsasync-awaites6-promisefs

Get all files within a folder containing string, push filenames to array and return array using Node FS


As the title describes, I would like to read all files from a specific directory and return the names of all the files that have a specific string in its contents.

Here is how my code looks so far:

const dirname = path.resolve("./results/");

async function readFiles(dirname) {
  const allResults = []
  fs.readdir(dirname, function(err, filenames) {
    if (err) {
      console.log(err);
      return;
    }
    filenames.forEach(async function(filename) {
      fs.readFile(dirname + "/" + filename, 'utf-8', function(err, content) {
        if (err) {
          console.log(err);
          return;
        }
        if (content.includes('content string')) {
          allResults.push(filename);
        }
      });
    });
  });
  return allResults;
}
readFiles(dirname).then((res) => {
  console.log(res);
})

The result I'm getting is []

so I understand it's an issue with promises and async functions, however, this is not a concept I fully grasp yet, and despite trying several combinations of possibilities (new Promise(), or .then, await, or readdirSync and readFileSync) I had no success.

What am I missing so that it returns the allResults array only once all files have been read?


Solution

  • You should ditch callback syntax and use fs.promises Api. This looks much cleaner

    const fs = require("fs").promises;
    const path = require("path");
    const dirname = path.resolve("./results/");
    
    async function readDir(dirname) {
      const allResults = [];
    
      try {
        const files = await fs.readdir(dirname);
    
        for (let i = 0; i < files.length; i++) {
          const fileName = files[i];
    
          try {
            const content = await fs.readFile(`${dirname}/${fileName}`, {
              encoding: "utf-8"
            });
    
            if (content.includes("content string")) {
              allResults.push(fileName);
            }
          } catch (error) {
            console.log(error.message);
          }
        }
    
        return allResults;
      } catch (error) {
        console.log(error);
      }
    }
    
    readDir(dirname).then(data => {
      console.log(data);
    });