Reputation: 43
I am trying to use file creation and deletion as a method of data transfer (not the best way, I know.) between python and nodejs. The python side of the program works fine, as I am quite familiar with python 3, but I can't get the node.js script to work.
I've tried various methods of detecting when a file is created, mainly with the use of try {} catch {}
, but none of them have worked.
function fufillRequest(data) {
fs.writeFile('Response.txt', data)
}
while(true) {
try {
fs.readFile('Request.txt', function(err,data) {
console.log(data);
});
} catch {
}
}
The program is supposed to see that the file has been created, read it's contents, delete it and then create and write to a response file.
Upvotes: 4
Views: 6040
Reputation: 56855
Existing answers are a bit old fashioned with async callbacks. Here's a more modern promise-based version tested in Node 18:
const fs = require("node:fs/promises");
const timers = require("node:timers/promises");
const waitForFile = async (
filePath,
{timeout = 30_000, delay = 200} = {}
) => {
const tid = setTimeout(() => {
const msg = `Timeout of ${timeout} ms exceeded waiting for ${filePath}`;
throw Error(msg);
}, timeout);
for (;;) {
try {
const file = await fs.readFile(filePath, {encoding: "utf-8"});
clearTimeout(tid);
return file;
}
catch (err) {}
await timers.setTimeout(delay);
}
};
// test it:
(async () => {
const file = "test.txt";
setTimeout(() => fs.writeFile(file, "hello world!"), 3000);
const content = await waitForFile(file);
console.log(content);
await fs.unlink(file);
})();
If you want, you can remove fs.readFile
from the waitForFile
function if you just want to know it exists or leave responsibility to the caller, rather than automatically read it. In this version, the for
loop body would look like:
try {
await fs.stat(filePath);
clearTimeout(tid);
return;
}
catch (err) {}
Upvotes: 1
Reputation: 707158
You can either user a recurring timer or fs.watch()
to monitor when the file appears.
Here's what it would look like with a recurring timer:
const checkTime = 1000;
const fs = require('fs');
function check() {
setTimeout(() => {
fs.readFile('Request.txt', 'utf8', function(err, data) {
if (err) {
// got error reading the file, call check() again
check();
} else {
// we have the file contents here, so do something with it
// can delete the source file too
}
});
}, checkTime)
}
check();
Note: Whatever process is creating this file should probably use an exclusive access mode when writing so that you don't create a race condition where it starts reading before the other process is done writing.
Upvotes: 2
Reputation: 8125
@jfriend00 solution is correct. However, In the above solution. It never cleans the timeout. It may cause an issue. If u need blocking code and better timer handling u can use setInterval.
Sample:
const checkTime = 1000;
var fs = require("fs");
const messageFile = "test.js";
const timerId = setInterval(() => {
const isExists = fs.existsSync(messageFile, 'utf8')
if(isExists) {
// do something here
clearInterval(timerId)
}
}, checkTime)
You can also run your python program. No need to write another script.
const spawn = require("child_process").spawn;
const proc = spawn('python',["./watch.py"]);
proc.stdout.on('data', (data) => console.log(data.toString()))
proc.stderr.on('data', (data) => console.log(data.toString()))
Upvotes: 4