I'm looping through files in a directory and storing the file details to an array data
. The following code populates the array if I don't attempt to run fs.stat
to get things like the file create/edit date:
fs.readdir('../src/templates', function (err, files) {
if (err) {
throw err;
}
var data = [];
files
.forEach(function (file) {
try {
fs.stat('../src/templates/'+file,(error,stats) => {
data.push({ Name : file,Path : path.join(query, file) });
});
} catch(e) {
console.log(e);
}
});
res.json(data);
});
});
If I move the data.push(...)
outside the fs.stat
the array returns with the file data. Inside the fs.stat
it returns empty. I assume this is an asynchronous issue in that the for loop is running and finishing before fs.stat
runs.
I'm thinking I need to use a promise here but unsure.
readdir() Method. The fs. readdir() method is used to asynchronously read the contents of a given directory. The callback of this method returns an array of all the file names in the directory.
__dirname: It is a local variable that returns the directory name of the current module. It returns the folder path of the current JavaScript file. Difference between process.cwd() vs __dirname in Node.js is as follows: process.cwd()
Method 1: Using fs. readdirSync() is a method that is available in the file system module of Node. js. It is used for reading the contents of a directory. It returns an array of file paths, buffers, or fs.
The promises object of the fs module was introduced in Node.js version 10, so some earlier versions still call the module experimental. This warning was removed when the API became stable in version 12.6. Now that you’ve read a file with the fs module, you will next create a file and write text to it.
If you don’t specify a flag, it defaults to w, which creates a new file if none exists or overwrites a file if it already exists. You can learn more about filesystem flags in the Node.js documentation. To complete your script, use these functions. Add the following highlighted lines at the end of the file:
You will create a CSV file in Node.js that keeps track of a grocery bill. The first time you write the file, you will create the file and add the headers. The second time, you will append data to the file. You will continue to use async/await syntax as you create two functions. The first function will be to make the CSV file.
Flags tell Node.js how to interact with the file on the system. By using the flag a, you are telling Node.js to append to the file, not overwrite it. If you don’t specify a flag, it defaults to w, which creates a new file if none exists or overwrites a file if it already exists.
If you want or need to be asynchronous:
const fs = require("fs");
const path = require("path");
const { promisify } = require("util");
const asyncStat = promisify(fs.stat);
fs.readdir('../src/templates', async function(err, files) {
if (err) {
throw err;
}
const data = await Promise.all(files.map(async function(file) {
try {
const stats = await asyncStat('../src/templates/' + file);
return { Name: file, Path: path.join(query, file), stats };
} catch (e) {
console.log(e);
}
}));
res.json(data);
});
Note that I used map
instead of forEach
and then awaited all Promises (async
makes function return a promise).
I also needed to change fs.stat
to use promise with util.promisify
.
You're right about the issue being in the asynchronous call. You could use a promise, or you could use fs.statSync(...)
, which returns a fs.Stats
object and operates synchonously.
files.forEach(function (file) {
try {
var fileStats = fs.statSync('../src/templates/' + file);
data.push({
Name : file,
Path : path.join(query, file)
});
} catch(e) {
console.log(e);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With