Reputation: 320
I have a text file containing paths per line (blanks are possible), e.g.
C:\Windows\system32
C:\Windows\system33
C:\Windows\DirectX.log
I then want to read this file line by line and determine if the file/direcotry on each line exists.
Following code works just fine:
const path = require("path");
const fs = require("fs-extra");
const readline = require("readline");
const FILE = path.join(__dirname, "file.txt");
(async () => {
const rl = readline.createInterface({
input: fs.createReadStream(FILE)
});
let lines = [];
await new Promise((resolve, reject) => {
rl.on("line", line => line && lines.push(line));
rl.on("close", () => resolve());
rl.on("error", err => reject(err));
});
for (let line of lines) {
console.log(line, await fs.pathExists(line));
}
})();
The output is:
C:\Windows\system32 true
C:\Windows\system33 false
C:\Windows\DirectX.log true
But I was wondering how could I check the file/folder existence as soon as I have the path, i.e. on "line" event. So I tried this:
const path = require("path");
const fs = require("fs-extra");
const readline = require("readline");
const FILE = path.join(__dirname, "file.txt");
(async () => {
const rl = readline.createInterface({
input: fs.createReadStream(FILE)
});
await new Promise((resolve, reject) => {
rl.on("line", async line => line && console.log(line, await fs.pathExists(line)));
rl.on("close", async () => {
console.log("close");
resolve();
});
rl.on("error", err => reject(err));
});
})();
And the result is:
C:\Windows\system32 true
C:\Windows\system33 false
close
C:\Windows\DirectX.log true
which is nothing unexpected. But how can I ensure the resolve()
is called only after all the promises from the "line" event are resolved?
Upvotes: 0
Views: 110
Reputation: 1721
You can push all the "line" event promises into an array and on "close" event use Promise.all()
, which resolvs when ALL promises on a given promises array is resolved, or rejected once one of the promises in the array rejects.
something like this:
let promisesArray = [];
let resArray = await new Promise((resolve, reject) => {
rl.on("line", line => promisesArray.push(fs.pathExists(line).catch( (reason) => { /* Handle Errors */ })));
rl.on("close", async () => {
console.log("close");
return Promise.All(promisesArray);
});
rl.on("error", err => reject(err));
});
and resArray
will hold an array of results per promise in the same location in promisesArray.
EDIT: as Bergi noted, Promise.All()
expects to be called right when all the promises are fired, but here they are fired with a "line" event which can cause a bit of delay. Hence, if one of them is rejected along the way, it is possible Promise.All()
was not yet called because "close" event havn't reached yet, so you'll get "Unhandled promise rejection" error which would crash your program. Handling errors when the promise is set guarentees correct error handling and no crashes :)
Upvotes: 3