NodeJs : why my Writablestream does not close before end of program? - node.js

I have a NodeJS script that I use to write JSON objects to file :
var reWriteCodes = function(arrayCodes, pathFileCodes, fs, typereWriteCodes, cb) {
console.log("message : "+ typereWriteCodes);
var codesStream = fs.createWriteStream(pathFileCodes, {'flags': 'w'});
codesStream.on('finish', () => {
console.log("the stream is closed")
if (typereWriteCodes === 0) {
cb();
}
});
var jsonToWrite = { "liste_codes" : arrayCodes};
codesStream.write(JSON.stringify(jsonToWrite));
codesStream.end();
}
This function is called twiced (first with typereWriteCodes = 0 then with typereWriteCodes = 1, inside the callback function : cb) with two different files.
The first call ends fine, my file is saved and the message "the stream is closed" displays in the console. But in the second call (which is the last operation of the program), my file is not saved correctly (the file is empty) and the message "the stream is closed" is not triggerd. Also, I get this message :
events.js:141
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open ''
at Error (native)
I have the feeling that the app is closing before the stream could end correctly ... But I do not know how I can do this correctly. Could you help me with this issue ? Any help appreciated.

Related

Crash when trying to load a file using Node's repl library

I am getting a crash at the indicated point below when the code attempts to load a file. The file contents are read and displayed on the console. But when the line
app.ports.receiveData.send(data.toString());
is (tried to) execute, the code crashes. I've attached the error message below the code. The JS code here is used to run some Elm code "headless". The app.ports... function call is supposed send data back to the Elm app. (The Elm Code is further down).
JS CODE:
const repl = require('repl');
const fs = require('fs')
// Link to Elm code
var Elm = require('./main').Elm;
var main = Elm.Tool.init();
// Eval function for the repl
function eval(cmd, _, _, callback) {
main.ports.put.subscribe(
function putCallback (data) {
main.ports.put.unsubscribe(putCallback)
callback(null, data)
}
)
main.ports.get.send(cmd)
}
main.ports.sendFileName.subscribe(function(data) {
var path = data
// console.log(path)
fs.readFile(path, { encoding: 'utf8' }, (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data.toString())
// Crash on next line !!!!
app.ports.receiveData.send(data.toString());
})
});
function myWriter(output) {
return output
}
console.log("\nType 'h' for help\n")
repl.start({ prompt: '> ', eval: eval, writer: myWriter});
Elm CODE
Here are the parts the Elm code that are relevant.
This code is called when the user wants to load a file.
loadFileCmd : String -> Cmd msg
loadFileCmd fileName =
sendFileName (E.string <| "./source/" ++ fileName)
These are the ports used to communicate with JS
port get : (String -> msg) -> Sub msg
port put : String -> Cmd msg
port sendFileName : E.Value -> Cmd msg
port receiveData : (E.Value -> msg) -> Sub msg
The get port listens for commands the user gives to the repl and gives these commands to Elm to process. The put port sends data that Elm computes to the repl.
The sendFileName port sends a file path to the repl. The receiveData port listens for the file contents. (But we crash before this can happen).
Here are the subscriptions:
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.batch [ Command.get Input, Command.receiveData ReceiveFileContents ]
ERROR MESSAGE:
repl.js:573
const lines = errStack.split(/(?<=\n)/);
^
TypeError: errStack.split is not a function
at Domain.debugDomainError (repl.js:573:30)
at Domain.emit (events.js:321:20)
at Domain.EventEmitter.emit (domain.js:485:12)
at Domain._errorHandler (domain.js:253:23)
at Object.<anonymous> (domain.js:156:29)
at process._fatalException (internal/process/execution.js:164:29)
From the comments, the answer was to replace the line
app.ports.receiveData.send(data.toString());
with
main.ports.receiveData.send(data.toString());
as the Elm app is named main, not app.

NodeJS fs.rename always thrown an error

I don't understand one thing with fs.rename(), why this code always throw an error?
The file is correctly renamed but each time i got this error Error: ENOENT: no such file or directory, rename '/path/to/file/example.log' -> '/path/to/file/example_1.log'
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});
When I run your exact code:
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});
(the only difference is adding the fs require).
Then I get the error when I don't have the file in the current directory.
But when I create example.log and run the program then I don't get any error and the file is renamed.
Of course next time I get the error again because I no longer have the file with the original name.
Are you sure that it doesn't work for you?
By the way, instead of
if (err instanceof Error)
you may want to use:
if (err)
Just in case that your error is not the instance of Error but still is defined (this can be true while using some modules).

Unhandled 'error' event when extracting zip file with nodejs

I want to download a zip file and extract it with nodejs. This is what I have done so far:
var fs = require('fs');
var wget = require('wget-improved');
var filesizeHumanReadable = require('filesize');
var unzip = require('unzip');
var downloadCSS = function() {
var src = 'http://7-zip.org/a/7za920.zip';
var output = '/tmp/7z.zip';
var options = {};
var download = wget.download(src, output, options);
download.on('error', function(err) {
console.log(err);
});
download.on('start', function(fileSize) {
console.log(filesizeHumanReadable(fileSize));
});
download.on('end', function(outputMessage) {
console.log(outputMessage);
console.log(output);
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/' }));
});
download.on('progress', function(progress) {
// code to show progress bar
});
}
The error message I get when running it:
mles-MacBook-Pro:test-api mles$ node index.js
375.83 KB
Finished writing to disk
/tmp/7z.zip
events.js:85
throw er; // Unhandled 'error' event
^
Error: EPERM, unlink '/tmp'
at Error (native)
Now I'm a bit baffled how to handle the error event and what my actual error is?
Does the process have enough permission to write to /tmp? Does /tmp already have some files?
Because unlink is a node.js function to delete directories. Apparently, unzip.Extract calls it. So, unlink fails if the folder isn't empty (in your case /tmp).
Setting the unzip location to a specific directory fixes it
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/7zip' }));
I'm marking mostruash answer as correct since he brought me on the right track.

Reading file with Node.js

I have a problem reading the stats of a file. I have this code:
var fs = require('fs');
process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
var stats =fs.statSync(chunk);
length=stats.size;
console.log(length);
}
});
When I exec this code I get this error:
return binding.stat(pathModule._makeLong(path));
^
Error: ENOENT, no such file or directory 'hello.txt
But the problem is that "hello.txt" actually exists at the same directory¡
I have tried with other files and I always get the same error.
Any ideas?
Thanks¡
The chunk read from the standard input contains a new line in the end, which was conflicting with your call to fs.statSync. Try this:
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null && chunk !== '') {
var stats = fs.statSync(chunk.trim()); // trim the input
length=stats.size;
console.log(length);
}
});
Also note that the function will be constantly executed for as long as 'readable' events are triggered. You may wish to terminate the program at some point or anything like that.

error ENOENT,open '/tmp/45e85388793de' in nodejs

I am trying to save project and its file in GridFS. I want to save project first and using "_id" of project as metadata for file I want to save file. When i tried so i am getting ENOENT, open '/tmp/45e85388793de' error. here is my code
newProject.save(function (err,project) {
if (err) {
console.log('save error', err);
}
console.log("project added");
var id=poject._id;
var filepath = req.files.file.path;
var filename = req.files.file.name;
var writestream = gfs.createWriteStream({ filename: filename, metadata:id });
console.log(filepath);
fs.createReadStream(filepath)
.on('end', function() {
})
.on('error', function(err) {
console.log("error encountered"+err);//ENOENT,open error
})
.pipe(writestream);
});
Why i am getting this error and how to resolve it?
ENOENT in this context means "No such file or directory." It means the filepath you are trying to read with createReadStream does not exist.
I think you are getting this error since :
Your file is saved in a temporary location.
When you are inside the callback function your file is removed from that location and you are getting "No such file" error. Path and other variables still exists as part of js and that's why you are able to print them in console.
Solution:
Above(Outside) callback function move your file to some other permanent location using:
fs.rename(req.files.file.path, "./someKnownPath/filename");
Keep note of that location. In your callback function use the new location as path and try saving the file in gridfs. Once the file is saved you may delete it file from that location(/someKnownPath/filename).
This error was occuring for me as well. And the reason was temp directory was not in place. After I created manually and gave a try, it worked.
Now I have shifted to creating directory on the fly through node.js itself.

Resources