I never get in the callback function, nodejs just stops - node.js

I always used nodejs together with express, but now I try to run the following script in nodejs (just by calling in the terminal "node myscript.js")
postModel is a mongoose model, doing a query on a mongodb.
'use strict'
var postModel = require(__dirname + '/../model/post').postModel;
myfunction();
function myfunction() {
console.log("before call");
postModel
.find({isArchived: false})
.exec(function(err,result){
console.log("result is ok")
})
};
so what I don't understand is why I never see "result is ok" in my terminal.
I also tried this with the async and wait.for library, but also there my script just stops before the async function is executed and a result is returned.
I think I just miss something in what I am doing, but no idea what...

You need to call mongoose.connect() to actually connect to a database.
Otherwise, Mongoose will queue your query internally and wait for a connection before issuing the query. However, since that connection never comes (because mongoose.connect() wasn't called), the queue is never processed, your query is never issued, and hence its callback will never get called.

Related

Mongoose post init async not working

Mongoose post 'init' is apparently unable to perform asynchronously as documented. I'm using the latest mongoose#5.0.10 and #types/mongoose#5.0.7 packages.
schema.post('init', function (doc, next: any) {
gunzipJSON(this.zipped).then(obj => {
this.categories = deserialize<Category[]>(Category, obj) || [];
next();
});
});
Also note my use of "next: any" to avoid a TS2349 error below on call to next(). When the hook fires, this and doc are set to a model. Before I upgraded to latest, I was using Mongoose 4.7.21 and next was supplied with a function(err) as expected, but the TS declaration must have been wrong.
Still, when the init hook function returns, the Mongoose init caller doesn't wait for my async decompression to complete and immediately returns the document to my client. When the decompression finishes, it correctly inflates and deserializes the field but it's too late. What am I doing wrong? I've tried numerous permutations of hook parameters to trigger async behavior without luck. Of course this happens when you're in a time crunch!
UPDATE:
I just now read 5.0 release notes https://github.com/Automattic/mongoose/blob/master/migrating_to_5.md: "init hooks are now fully synchronous and do not receive next() as a parameter. Document.prototype.init() no longer takes a callback as a parameter. It was always synchronous, just had a callback for legacy reasons."
Yikes! How does one apply post load async hooks?

node async call return data in response

I am new to nodejs so I have a basic question and this is my scanrio
I have a javascript client which is making a http request to a node server to read a value from the database.
Once the node server receives the request it makes a simple db call and returns the data to the client in the response, and this is where the problem is.
router.get('/state', function(req, res){
var result = dbServer.makeDBCall();//Before this line executes and returns the result the next line executes
res.send(result);
}
The database call from the node server is asynchronous, therefore before the result is returned the node server has already sent a blank response to the client. What is the standard/acceptable way of getting this achieved, I know I can block the node thread using async, but then the whole purpose of node is gone right?
It depends on what kind of database node module you are using.
Other than the standard callback approach, there are also the promise way. The pg-promise library is 1 of those kind.
See sample code:
this.databaseConnection.makeDBCall('your query...')
.then(function(dbResponse) {
// Parse the response to the format you want then...
res.send(result);
})
.catch(function(error) {
// Handle error
res.send(error.message);
});
#spdev : I saw 1 of your comments about you being worried about how Node actually knows who to reply the response to, especially when there are multiple requests.
This is a very good question, and to be honest with you - I don't know much about it as well.
In short the answer is yes, Node somehow handles this by creating a corresponding ServerResponse object when a HTTP request comes through. This object seems to have some smartness to tell the Nodejs network stack how to route itself back to the caller when it gets parsed as data packets.
I tried Googling a bit for an answer but didn't got too far. I hope the ServerResponseObject documentation can provide more insight for you. Share with me if you got an answer thanks!
https://nodejs.org/api/all.html#http_class_http_serverresponse
Try below code.
router.get('/state', function(req, res){
var result = dbServer.makeDBCall(function(err,result){
if(!err) {
res.send(result);
}
});
}
Hope this Help.
The dbServer.makeDBCall(); must have a callback that runs when the statement completes executing.
Something like -
dbServer.makeDBCall({query: 'args'}, function(err, result){
if (err) // handle error
res.send(result);
})
You return the response from db from that callback function.
Learn more about callback from here-
nodeJs callbacks simple example
https://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks/

Mongoose Model.count() does not run callback as documented

I am following almost the exact example for Model.count() from the Mongoose docs:
User.count({ type: 'jungle' }, function (err, count) {
console.log('I do not ever run');
});
This should print 'I do not ever run'. Instead, it returns a Query object - which should not happen, according to the docs, as I am providing a callback. How can I make the callback function run? Is there some circumstances where the callback is not run?
Using mongoose#3.6.17. Thanks!
Make sure you've connected to the database before calling any model functions. Mongoose will just queue up the count query until you connect otherwise.
See this question of the FAQ.

Meteor blocking clarification

According to the meteor docs, inserts block:
On the server, if you don't provide a callback, then insert blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, insert still
returns the ID immediately.
So this would be wrong:
Meteor.methods({
post: function (options) {
return Stories.insert(options)
}
});
I need to do this:
Meteor.methods({
post: function (options) {
return Stories.insert(options, function(){})
}
});
Can somebody confirm that this is the case? The former will block the ENTIRE SERVER until the db returns?
Yeah, it will block, but not the entire server.
In Meteor, your server code runs in a single thread per request, not in the asynchronous callback style typical of Node. We find the linear execution model a better fit for the typical server code in a Meteor application.
So, if you are worried about that it will block the entire server as it will do in typical Node, don't be.

Mongoose and commander

I'm writing some scripts for some command-line manipulation of Mongoose models with commander.js (eventually, I'd like to run these tools using Cron).
Now, I've written several scripts with commander and they all work fine, but if I connect to the MongoDB database using mongoose, they script just hangs after it's done. Now, I figured the database connection is keeping node alive, so I added a mongoose.disconnect() line and it still hangs.
The only thing I found that allows me to shutdown is to use process.exit(), but I'm reluctant to just terminate the process. Is there something in particular that I should do to trigger a graceful shutdown?
My reading of the API docs implies that .disconnect() must be given a callback function. It looks like it's called for each that's disconnected and may be passed an error.
There is a check in the code to make sure it's not called if it doesn't exist when things work out, but that check isn't being run on errors, so if Mongoose received an error message from the MongoDB client, it may be leaving a connection open and that's why it's not stopping execution.
If you're only opening a single connection to the database, you may just want to call [Connection object].close() since that function correctly inserts a no-op "callback" if no callback is given, and looks like it will correctly destruct things.
(The more I look into Mongoose, the more I want to just write a thin wrapper around the MongoDB client so I don't have to deal with Mongoose's "help.")
I use the async "Series" to perform operations and then call mongoose.connection.close() on completion. It prevents callback hell and allows you to neatly perform operations either one at a time or parallel followed by a function when all the other methods have completed. I use it all the time for scripts that require mongoose but are meant to terminate after all mongoose operations are finished.
Shutdown the node program directly is hiding the symptoms, not fixing the problem!
I finally isolated the problem and found it to be with Mongoose schema definitions. If you try to shutdown the connection too soon after Mongoose schemas are defined1, the application hangs and eventually produces some weird MongDB-related error.
Adding a small timeout before running the program.parse(argv) line to run the commander application fixes the problem. Just wrap the code like so:
var program = require('commander')
, mongoose = require('mongoose')
, models = null
;
// Define command line syntax.
program
.command(...)
;
mongoose.connect(
..., // connection parameters.
function() {
// connected to database, defined schemas.
models = require('./models');
// Wait 1 second before running the application code.
setTimeout(function(){
program.parser(process.argv);
}, 1000);
}
);
1: This is my initial interpretation, I have not (yet) extensively tested this theory. However, removing Mongoose schema definitions from the application successfully prevents the application from hanging.
Actually, just using process.nextTick() instead of the setTimeout() call fixes the situation nicely!

Resources