I'm new to node.js and I'm struggling with this problem. I don't understand why my output is
ciao
data
data
and not
data
data
ciao
This is my code
fs.readdir("sender", (err, files) => {
if (err) {
throw err;
}
const path = __dirname + "/sender/";
let rawdata = fs.readFileSync(path + "data.json");
var data = JSON.parse(rawdata);
files.forEach((file) => {
fs.stat(path + file, (err, stats) => {
if (err) {
throw err;
}
if (data[file]["size"] != stats.size) data[file]["size"] = stats.size;
if (data[file]["time"] != stats.mtime.toISOString()) data[file]["time"] = stats.mtime.toISOString();
console.log("data");
});
});
console.log("ciao");
});
I've read that foreach is not asynchronous, so I don't really understand why the output is reversed.
forEach is not asynchronous. But the operation you're doing in the forEach callback, fs.stat, is asynchronous.
So what your code is doing is starting a series of fs.stat operations (two, it looks like), then logging ciao, then later when each of those fs.stat operations completes, it's logging data.
You could use the promise-based file system API instead, and use async/await; see comments:
const {readdir, readFile, stat} from "fs/promises";
// This version of `readdir` returns a promise
fs.readdir("sender")
.then(async files => { // Use an `async` function as the fulfillment callback
const path = __dirname + "/sender/";
// Await the promise from `readFile` (no need to use `readFileSync`)
const rawdata = await readFile(path + "data.json");
const data = JSON.parse(rawdata);
// Wait for all operations to complete (they run in parallel)
await Promise.all(files.map(async file => {
// Get the stats (again, awaiting the promise)
const stats = await stat(path + file);
// Update the entry for the file.
const entry = data[file];
if (entry.size != stats.size) { // (There's no point to this comparison, just do the assignment)
entry.size = stats.size;
}
if (entry.time != stats.mtime.toISOString()) { // (Again)
entry.time = stats.mtime.toISOString();
}
console.log("data");
}));
// Since this is after the `await` on the promise from `Promise.all`, it doesn't run until all
// of the promises `Promise.all` was waiting on have been fulfilled
console.log("ciao");
})
.catch(error => {
// ...log/handle error...
});