Victor
Victor

Reputation: 152

How to await fs.readFile?

I'm having problems with awaiting fs.readFile() I have a file where I want to iterate over each line, and save non-duplicated inside of an array domains.

However, when I call my function with fs.readFile and after it I call console.log(domains) domains is empty.

Code

var fs = require("fs");
var re = /@(.*?):/;
let domains = [];

const parseProviders = () => {
    fs.readFile("file.txt", (error, data) => {
    if (error) throw error;
    data
      .toString()
      .split("\n")
      .forEach((line, index, arr) => {
        try {
          line = line.match(re)[1];
          if(!domains.includes(line)) {
            domains.push(line);
          }
        } catch (err) {
          throw err;  
        }
      });
      console.log(domains); // this would work and print an array with non-duplicate items
  });
}

(() => {
  parseProviders();
  console.log(domains); // prints an empty array []
})();

Upvotes: 3

Views: 5785

Answers (2)

Ben Wainwright
Ben Wainwright

Reputation: 4611

There are a number of different things you could do here. (note that in the below code samples I've deliberately simplified things to make them easier to read) You could

1. Amend your function to take a callback that gets executed by the readfile callback

const parseProviders = (callback) => {
    fs.readFile("file.txt", (error, data) => {
      data
        .toString()
        .split('\n')
        .forEach(line => domains.push(line))
    });
  });
}

(() => {
  parseProviders(() => {
    console.log(domains);
  });
})();

2. Make use of the fs/promises module as suggested by @robertklep in the comments. If you do this you should turn it into an async function

const  { readFile } = require("fs/promises")

const parseProviders = async (callback) => {
    const data = await readFile("file.txt")
    data
      .toString()
      .split('\n')
      .forEach(line => domains.push(line))
  });
}

(async () => {
  await parseProviders()
  console.log(domains);
})();

3. Manually promisify the readFile function.

const parseProviders = () => {
    return new Promise((accept, reject) => {
      fs.readFile("file.txt", (error, data) => {
      data
        .toString()
        .split('\n')
        .forEach(line => domains.push(line))
        accept();
      });
  });
}

(async () => {
  await parseProviders()
  console.log(domains);
})();
  • Note - you don't need to do this, but its worth knowing how to do it for when you are dealing with other callback style APIs.

Upvotes: 8

mohammad Naimi
mohammad Naimi

Reputation: 2359

you could use callback

var fs = require("fs");
var re = /@(.*?):/;
let domains = [];

const parseProviders = (callback) => {
    fs.readFile("file.txt", (error, data) => {
    if (error) throw error;
    data
      .toString()
      .split("\n")
      .forEach((line, index, arr) => {
        try {
          line = line.match(re)[1];
          if(!domains.includes(line)) {
            domains.push(line);
          }
        } catch (err) {
          throw err;  
        }
      });
      console.log(domains); // this would work and print an array with non-duplicate items
      callback(domains)
  });
}

(() => {
  parseProviders((res)=>{
  console.log(res); // prints an empty array []

});
})();

Upvotes: 1

Related Questions