Writing to a .txt file before node.js exits - javascript

I'd like my server to save some essential data when node exits and load them next time.
I tried what the answer of this question suggested, but the server seems to close before it is able to write to the file.
This is the exact code I am trying:
process.stdin.resume();
function exitHandler(options, err) {
if(!serverUp){return;}
serverUp = false;
fs.writeFile('server.txt', String(search_index),function (err) {
console.log("debug") // <-- This doesn't happen
process.exit();
});
}
//do something when app is closing
process.on('exit', exitHandler.bind(null,{cleanup:true}));
//catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, {exit:true}));
//catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));

I think if you tried fs.writeFileSync it would solve this.
https://nodejs.org/api/fs.html#fs_fs_writefilesync_filename_data_options
The code would then be:
function exitHandler(options, err) {
if(!serverUp){return;}
serverUp = false;
fs.writeFileSync('server.txt', String(search_index));
console.log("debug");
process.exit(); // Don't think you'll need this line any more
}
The issue I believe is because of the async nature. By using the synchronous version of writeFile you're forcing the process to finish executing everything before exiting.

Related

Multiple errors when trying to save to DB using mongoose and async

i am trying to save something to a database using mongoose. The thing is i need to make sure the save was completed before i move on in the program and close the connection. Knowing that save is async in mongoose i tried using this code:
saveFunction = function(song){
song.save(function(err, userObj){
if(err){
console.log('Error' + err);
} else{
console.log('saved successfully:', userObj);
}
});
};
database.prototype.add= function(newSong){
mongoose.connect(url);
var song = new songModel({id : newSong.getId(),
title : newSong.getTitle(),
artist : newSong.getArtist,
genre : newSong.getGenre(),
rating : newSong.getRating(),
link : newSong.getLink()});
console.log("before async");
async.parallel([function (callback){
saveFunction(song);
callback();
}],function(){
mongoose.connection.close();
console.log('closed connection');
});
console.log("after async");
nextFreeId++;
};
^songModel is defined globally.
I tried lots of different methods and changed lots of thing but i always get and error of somekind. With this code i get a process.nexttick(function() throw err ) error. I just can't get it to work. Can someone tell me whats wrong or provide me with working code?
I think optimally the console should look like this:
before async
saved successfully
closed connection
after async
Thanks!
EDIT: Open to other alternatives to async aswell. I just want to get this code to work any way possible. I just need to save/find something/remove something and it needs to wait with the rest of the execution of the program until the save/find/removal is done. I'm getting pretty desperate, lost nearly a day on this problem alone on a tight shedule :(
You need to return a callback from your save function.
saveFunction = function(song,callback){
song.save(function(err, userObj){
if(err){
console.log('Error' + err);
return callback(true,err)
} else{
console.log('saved successfully:', userObj);
return callback(null);
}
});
};
Edit
From your comment, the behavior you are expecting will never occur. You are expecting
console.log("before async");
async.parallel -> do your bits
console.log('closed connection');
console.log("after async");
However this will never happen because async.parallel is an asynchronous call, which means that the execution does not wait for it to finish before moving onto the next command. The behavior you are seeing is
console.log("before async");
async.parallel -> starts
console.log("after async");
async.parallel -> console.log('closed connection');
Node is doing the first log, starting the async.parallel, then console.logging "after async". Then when async.parallel gets to its callback function, it prints "closed connection", so it appears after "after async" because it was executed after.
Any logic you want to perform that relies on the result of async.parallel must happen in the callback function. Furthermore, async.parallel is used when you want to run 2 or more functions asynchronously, then execute a callback once they are all finished. Your solution does not require async.parallel. You can replace that with:
saveFunction(song,function(err){
if(err){
//failed to save song
}
mongoose.connection.close(); //you do not need to do this anyway
console.log('closed connection');
nextFreeId++;
//anything else you need to do here
});

Blocking Node in Script

I'm using Node.js to write system scripts that run on a server. Due to Node's asynchronous nature, my script is exiting before the database calls have a chance to complete and nothing is ever written to the database.
I'm using Mongoose as an ORM and talking to a MongoDB, if that makes any difference. Node.js offers SYNCHRONOUS method calls for this very reason, for example: https://nodejs.org/api/child_process.html
I guess my questions are:
1) Does mongoose offer a way to block so my scripting process can wait for the database call to return?
2) If not, is there another method I should consider other than something like:
(function wait () {
if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();
3) Is node not the best tool for the job for writing scripts? I love node for web app development, and can write nested callbacks or work with promises all day long. But what about as a scripting language?
EDIT -----------------------------------------------
Below is an quick example of the script to provide more clarity of the situation:
#!/usr/bin/env node
# Please note the above that this is a bash script
var schema = mongoose.Schema({
// ... attributes ...
});
var model = new (mongoose.model('ModelObject'))();
model['attribute'] = 42;
console.log('This gets printed first');
model.save(function(err) {
console.log('Nothing in the callback gets printed because callback is never called');
if(err) { // Can't check for errors because this is never reached
console.log('This never gets printed to the screen');
console.log('And consequently nothing is ever saved to mongo');
} else {
console.log('This never gets printed either');
}
});
console.log('This gets printed second');
If your model does not get saved, there is a Mongo error. Following MongoDB conventions you have to check for errors:
model.save(function(error, savedItem) {
if(error) {
// nothing is saved
}
});
Otherwise, have you considered using Promises? It useful for chaining events and simpler error handling.
Promise = require('bluebird');
Promise.promisifyAll(mongoose.Query.base);
model.saveAsync().then(function(savedItem) {
// saved
})
.catch(function(error) {
// handle error
});
I think you are looking for this, check below if this help you.
var mongoose = require('mongoose'),
model1 = mongoose.model('model1'),
model2 = mongoose.model('model2');
model1.findOne({"type" : 'Active'}, function err(err, catConfig) {
if(!err.error){
//This will execute once above DB call is done!
model2.findOne(condition).remove(function(err, gAnalysis) {
//Lines of code that you want to execute after second DB call
});
}
});
I don't see you opening a connection to the database so presumably saving a model instance does nothing, not even call the callback with an error...
I've tested the below example:
test.js:
var mongoose = require('mongoose');
var kittySchema = mongoose.Schema({
name: String
});
var Kitten = mongoose.model('Kitten', kittySchema);
mongoose.connect('mongodb://localhost:27017/test', function (err) {
if (err) throw err;
var silence = new Kitten({ name: 'Silence' });
silence.save(function (err, saved) {
if (err) throw err;
console.log('Kitty Silence is saved!');
mongoose.disconnect(function (err) {
if (err) throw err;
console.log('done...');
});
});
});
Running node test.js prints this to the console:
Kitty Silence is saved!
done...
and examining my local test database shows that Silence is indeed saved.

Files is deleting before its used in node js

I'm new to node js and i'm trying to do the following:
function createPasswordfile(content)
{
fs.writeFile(passwordFileName,content, function(err) {
if(err) {
console.log("Failed on creating the file " + err)
}
});
fs.chmodSync(passwordFileName, '400');
}
function deletePasswordFile()
{
fs.chmodSync(passwordFileName, '777');
fs.unlink(passwordFileName,function (err) {
if (err) throw err;
console.log('successfully deleted');
});
}
and there are three statements which call these functions:
createPasswordfile(password)
someOtherFunction() //which needs the created password file
deletePasswordFile()
The problem I'm facing is when I add the deletePasswordFile() method call, I get error like this:
Failed on creating the file Error: EACCES, open 'password.txt'
successfully deleted
Since its non blocking, I guess the deletePasswordFile function deletes the file before other function make use of it.
If deletePasswordFile is commented out, things are working fine.
How should I prevent this?
writeFile is asynchronous, so it's possible the file is still being written when you try and delete it.
Try changing to writeFileSync.
fs.writeFileSync(passwordFileName, content);

Nested callbacks in javascript

I have a small problem with nested callbacks in javascript. Apparently im doing something wrong, but i did my research and tried to follow the tutorials avaialble throughout the web. I know that my code works, since query returns proper data, but i have no idea why my code doesnt "wait" within executeQuery method till the res is fetched from database, it just goes straight to "oh noes" section.
DatabaseConnection.prototype.executeQuery = function(query, executeQueryDone){
var activeConnection;
console.log("YEAAA, executing Query: " + query);
this.pool.getConnection(function (err, connection){
console.log("Got Connection, we are ready to go!");
if (err){
console.log("Error, DAMMNIT! " + err);
executeQueryDone(err);
}
activeConnection = connection;
activeConnection.connect();
activeConnection.query(query, function(error, res){
console.log("Connection from pool is executing Query");
if(error){
console.log("Error during executing query");
executeQueryDone(error);
}
else {
console.log(" OK now release connection (dont be selfish)! ");
activeConnection.release();
executeQueryDone(null, res);
}
});
});
console.log("oh noes! IM AFTER CONNECTION, why dude? WHY???? ");
};
I'd be grateful for any hints since im struggling with that since yesterday.
=====================
PROBLEM SOLVED:
generally all was OK, the "issue" was mistakenly written test:
i made it like that:
describe('testDB2', function () {
it('should return proper STUFF', function (done) {
assert.equal(1, someService.getStuff(function(err, result){
if (err === null){
console.log("err is null, as it should be!");
}
console.log(" result from DB " + result[1].NUMBERS);
}));
});
});
while is should be like that:
describe('testDB2', function () {
it('should return proper STUFF', function (done) {
someService.getStuff(function(err, result){
assert.equal(err, null);
assert.equal(result[1].NUMBERS, 43637654);
done();
});
});
});
as a result (in the incorrect case), i didnt fetch the result the way i wanted as assert couldnt "catch up"
thanks to all for the enlightment ;)
Your console.log call isn't part of a callback, so it will be called as soon as the getConnection call is made. If you want it to be called only after your callback to getConnection fires, you either need to call it at the end of that call, or you need to use some form of promises.
Javascript is single threaded, but it does use a task queue. When the database connection is instantiated and the pool connected to, the response to that is placed into the task queue to be executed or actioned when complete.
Directly after placing that in the task queue the next piece of execution is the log that does the "oh noes" - nice messaging btw lol.
So essentially what happens is the db call gets placed in the task queue for later execution, and then the log occurs, and then the task queue executes at a later time with the db response.

Call a function in node.js

I am new to node.js .Here I write a sample function in node.js to print the contents of a json file as follows.
exports.getData =function(callback) {
readJSONFile("Conf.json", function (err, json) {
if(err) { throw err; }
console.log(json);
});
console.log("Server running on the port 9090");
What I am doing here is I just want to read a json file and print the contents in console. But I do not know how to call the getData function. While running this code it only prints the sever running on the port..", not myjson` contents.
I know the above code is not correct
How can I call a function in node.js and print the json contents?
Node.js is just regular javascript. First off, it seems like you are missing a }. Since it makes the question easier to understand, I will assume that your console.log("Server... is outside exports.getData.
You would just call your function like any other:
...
console.log("Server running on the port 9090");
exports.getData();
I would note that you have a callback argument in your getData function but you are not calling it. Perhaps it is meant to be called like so:
exports.getData = function(callback) {
readJSONFile("Conf.json", function (err, json) {
if(err) { throw err; }
callback(json);
});
}
console.log("Server running on the port 9090");
exports.getData(function (json) {
console.log(json);
});
Truthfully, your getData function is a little redundant without any more content to it since it does nothing more than just wrap readJSONFile.
Don't take this the wrong way, but your code appears to be a mixed up mess of unrelated examples. I recommend you start by learning the basics of JavaScript and node.js (for example, read Eloquent JavaScript and Felix's Node.js Beginners Guide).
But on to your code. First of all, you are creating a function (called getData) and exporting it. Then you're printing "Server running on the port 9090". There is no server code in your script, and the function you created is never executed.
I think this is what you intended to write:
readJSONFile("Conf.json", function (err, json) {
if(err) { throw err; }
console.log(json);
});
Assuming that readJSONFile is a real function.

Categories

Resources