I have a main in nodejs for my program where I need to use my result calculated in a module, but my I don't have the right result.
var myJSONClient = {
"nombre" : "<nombre_cliente>",
"intervalo" : [0,0]
};
var intervalo = gestionar.gestion(myJSONClient,vector_intervalo);
console.log("intervalo: "+intervalo); //return undefined
And this is the module
var gestion = function(myJSON,vector_intervalo) {
var dburl = 'localhost/mongoapp';
var collection = ['clientes'];
var db = require('mongojs').connect(dburl, collection );
var intervalo_final;
function cliente(nombre, intervalo){
this.nombre = nombre;
this.intervalo = intervalo;
}
var cliente1 = new cliente(myJSON.nombre,myJSON.intervalo);
db.clientes.save(cliente1, function(err, saveCliente){
if (err || !saveCliente) console.log("Client "+cliente1.nombre+" not saved Error: "+err);
else {
console.log("Client "+saveCliente.nombre+" saved");
intervalo_final = calculate(vector_intervalo);
console.log(intervalo_final); //here I can see the right content of the variable intervalo_final
}
});
setTimeout(function(){
console.log("pause");
},3000);
console.log(intervalo_final); //result not correct
return intervalo_final;
}
exports.gestion = gestion;
I know that node execute my return without wait the end of my function, for this I can't see the right result, but how can I force my program to wait the end of my function?
I tried with the setTimeout function but wasn't the right way.
You must implement your function just like the other async functions from the API!
First step : give callback to function
var gestion = function(myJSON,vector_intervalo, callback) {
Second step : when the async process is over call callback passing the result (you don't need the return line)
console.log(intervalo_final); //here I can see...
callback(intervalo_final);
Step three: use your function in an async way
gestionar.gestion(myJSONClient,vector_intervalo, function(result){
console.log(result);
});
In async JS you can't return a value the way it seems you trying to do. You need to pass a callback function from your main program when calling gestionar.gestion() (you can add it as a third argument).
Your code sample won't work because function gestion() returns immediately, before intervalo_final content is set.
Something like this:
gestionar.gestion(myJSONClient,vector_intervalo, function callback(intervalo) {
// This is the callback function
console.log("intervalo: " + intervalo);
});
And then within the function:
var gestion = function(myJSON,vector_intervalo, callback) {
...
db.clientes.save(cliente1, function(err, saveCliente) {
if (err || !saveCliente) {
console.log("Client "+cliente1.nombre+" not saved Error: "+err);
if (callback) callback(); // execute callback function without arguments
}
else {
console.log("Client "+saveCliente.nombre+" saved");
intervalo_final = calculate(vector_intervalo);
console.log(intervalo_final);
if (callback) callback(intervalo_final); // your callback function will be executed with intervalo_final as argument
}
});
Also, I highly recommend reading some async javascript tutorial, like http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
And Felix's Node.js Guide: http://nodeguide.com/
Related
I am using a node-powershell module from https://www.npmjs.com/package/node-powershell.
var shell = require('node-powershell');
PS = new shell('echo "node-powershell is awesome"');
PS.on('output', function(data){
console.log(data);
});
PS.on('end', function(code) {
//optional callback
//Do Something
});
I am trying to return data from a function and assign it to a variable $returneddata:
function getData()
{
var shell = require('node-powershell');
PS = new shell('echo "node-powershell is awesome"', {debugMsg: false});
PS.on('output', function(data){
return data;
});
PS.on('end', function(code) {
});
}
var $returneddata = getData();
But it does not assign it.
You are not seeing the data because your return statement is returning it to the wrong caller :) PS.on('output' ... is registering a callback function for an event. The provided function will then be called by the event emitter when the event is raised. Therefore, the value returned by this callback is actually being returned to the event emitter, who doesn't care about your return value, rather than the caller of getData.
To correct the issue, you should provide a callback of your own, try this:
function getData(callback) {
var shell = require('node-powershell');
PS = new shell('echo "node-powershell is awesome"', {debugMsg: false});
PS.on('output', function(data){
return callback(null, data);
});
PS.on('end', function(code) {
});
}
getData(function onGetData(err, data) {
// do stuff with the returned data here
});
As an aside, you may not need the err parameter, but error-first callbacks are the convention in node. You should probable add PS.on('error' ... if the module supports it...
i have a sample function in which i want to trigger 3 sql queries in one express post request
function getRelatedSalespersonByCardcode(req, res) {
var reqJson = JSON.parse(req.body.json);
var count = Object.keys(reqJson.cardcode).length;
var tmpResult1, tmpResult2, tmpResult3 = [];
var q = sql.open(connstr, function (err) {
if (err) {
console.log(err);
return;
}
for (var i = 0; i < count; i++) {
q.queryRaw("SELECT Division, Salesperson FROM SomeDB.dbo.MS2_Rel_BusinessPartnerSalesperson WHERE CardCode = " + reqJson.cardcode[i], function (e, results) {
if (e) {
console.log(e);
return;
}
tmpResult1.push(results);
});
q.queryRaw("SELECT SlpCode, SlpName, Memo, Commission, GroupCode, UserSign, Active, U_wpABIS, U_sweDW," +
" U_sweATT, U_sweDIV, U_sweEMPLOYEE, U_sweRETAILER FROM SomeDB.dbo.OSLP WHERE U_sweId = " + tmpResult1[1], function (e, results) {
if (e) {
console.log(e);
return;
}
tmpResult2.push(results);
});
q.queryRaw("SELECT Code, Name, U_sweSALES FROM SomeDB.dbo.[#SWEDIV] WHERE Code = " + tmpResult3[0], function (e, results) {
if (e) {
console.log(e);
return;
}
tmpResult3.push(results);
});
}
});
res.send(200, tmpResult2);
}
Anyway after 1 function is called inside my req, res function the callback is triggert.. so it jumps directly to the res.send(...) line.
i've played a bit around and it seems that this is how express works.
after a bit of googleing around i found out that i have to use the async lib.
i'd like to ask why express is working like this and if anybody maybe have a better solution than the async approach. i simply need a way to realize my scenario.
This is no issue of express and no issue at all. This is like node.js async programming is working. Let's examine what's happening in your code:
var tmpResult2;
// 1. async open sql connection
var q = sql.open(connstr, function (err) {
// 3. query sql connection
});
// 2. render result
res.send(200, tmpResult2);
SQL connection is opened asynchronously.
Express render is called.
SQL queries are executed.
As a consequence this code piece sends data to the client before the data was fetched. So the most simple solution is to invoke res.send inside of the callback like this:
var tmpResult2;
// 1. async open sql connection
var q = sql.open(connstr, function (err) {
// 2. render result
res.send(200, tmpResult2);
});
You can use the wonderful async module to deal with the queries (Take a look at the async waterfall function).
How do I set a variable to a query? I am trying to use functions and callbacks in node.js to work through async, but I am not sure how to get a query to equal to a variable. What I am trying to do in this code is take a friend collection that belongs to a user and return the friends result(which I don't think I am doing correctly in the query insertAll) and then find the user's info for each of the query. And then return the results as a render. I am not sure how to call render either with this...
Here is my code:
exports.contactList = function(req, res) {
var insertFriend = function(data, callback) {
var friend = User.findById({_id: user.friendStatus.fuId}, function() {
callback(null, data);
}, friend);
};;
var insertAll = function(coll, callback) {
var queue = coll.slice(0),
friendX;
(function iterate(){
if(queue.length === 0) {
callback();
return;
}
friendX = queue.splice(0,1)[0];
insertFriend(friendX, function(err, friendX) {
if(err) {throw err;}
console.log(friendX + ' inserted');
process.nextTick(iterate);
});
})();
};
insertAll([Friend.findOne({userId: req.signedCookies.userid})], function(){
});
};
A Query object is returned if you do not pass a callback.
From http://mongoosejs.com/docs/queries.html:
When a callback function:
is passed, the operation will be executed immediately with the results passed to the
callback.
is not passed, an instance of Query is returned, which provides a special QueryBuilder
interface for you.
NEW POST:
Here is the sample of the working async code without a db.
The problem is, if i replace the vars (data1_nodb,...) with the db.collection.find();
function, all needed db vars received at the end and the for() loop ends not
correct. I hope that explains my problem a bit better. OA
var calc = new Array();
function mach1(callback){
error_buy = 0;
// some vars
for(var x_c99 = 0; x_c99 < array_temp_check0.length;x_c99++){
// some vars
calc[x_c99] = new Array();
calc[x_c99][0]= new Array();
calc[x_c99][0][0] = "dummy1";
calc[x_c99][0][1] = "dummy2";
calc[x_c99][0][2] = "dummy3";
calc[x_c99][0][3] = "dummy4";
calc[x_c99][0][4] = "dummy5";
function start_query(callback) {
data1_nodb = "data1";
data2_nodb = "data2";
data3_nodb = "data3";
data4_nodb = "data4";
calc[x_c99][0][0] = data1_nodb;
calc[x_c99][0][1] = data2_nodb;
calc[x_c99][0][2] = data3_nodb;
callback(data1_nodb,data2_nodb,etc..);
}
start_query(function() {
console.log("start_query OK!");
function start_query2(callback) {
data4_nodb = "data5";
data5_nodb = "data6";
data6_nodb = "data7";
calc[x_c99][0][3] = data4_nodb;
calc[x_c99][0][4] = data5_nodb;
callback(data5_nodb,data6_nodb,etc..);
}
start_query2(function() {
console.log("start_query2 OK!");
function start_query3(callback) {
for(...){
// do something
}
callback(vars...);
}
start_query3(function() {
console.log("start_query3 OK!");
});
});
});
}
callback(calc);
};
function mach2(callback){
mach1(function() {
console.log("mach1 OK!");
for(...){
// do something
}
});
callback(calc,error_buy);
};
mach2(function() {
console.log("mach2 OK 2!");
});
OLD POST:
i try to read data from the mongodb and send them back with a callback to the next
function, that needs the infos from the db to proceed.
Without the mongodb read functions it works perfect but now i dont know how
i can send the db vars out of the two inner functions to the first callback function.
Hope someone can help me...
Thanks
var error = 0; var var1 = "yessir";
function start_query(callback) {
var db_name = "db1";
db[db_name].find({name:var1},{data1:1, data2:1, data3:1, data4:1}, function(err, data_catch,callback) {
if( err || !data_catch ) {
console.log("Problem finding data_catch:" + err);
} else {
data_catch.forEach( function(data_catch_finder,callback) {
data1_db = data_catch_finder.data1;
data2_db = data_catch_finder.data2;
data3_db = data_catch_finder.data3;
data4_db = data_catch_finder.data4;
if(data1_db == "" || data2_db == "" || data3_db == "" || data4_db == ""){error = 1; console.log("Error: data_catch_finder");}
callback(data1_db, data2_db, data3_db, data4_db, error);
});
}
});
callback(data1, data2, data3, data4, error);
}
//########################################################################
start_query(function() {
function start_query2(callback) {
console.log("DATA1 from callback:" + data1_db);
console.log("DATA2 from callback:" + data2_db);
console.log("DATA3 from callback:" + data3_db);
console.log("DATA4 from callback:" + data4_db);
var var_no_db = "testing";
//do something else and callback
callback(var_no_db);
}
start_query2(function() {
console.log("Var from callback start_query2:" + var_no_db);
console.log("The end");
});
});
your callback signature are issuing callback as a parameter.
As far as I can understand your code, you need to keep reference of the first callback, the one you receive here: function start_query(callback).
In every callback function you made the mistake to bind the variable name callback to the parameter from the mongo driver (a simple undefined i think).
You can fix it removing every reference of callback from the signature of your inner functions.
a simple example:
function async (cb) {
// params: Error, data
cb(null, 'moo');
}
function foo(callback) {
async(function(err, data, callback){
console.log(callback); // undefined
});
console.log(callback); // Moo
}
foo('Moo');
Take a look at Eloquent Javascript to better understand the JS context switching;
edit
The only way to wait the results of an async function is recall the first callback inside the last nested callback.
function ugly_nested (callback) {
dbquery('...', function(err, data_01) {
if (!! err) return callback(err);
dbquery('...', function(err, data_02) {
if (!! err) return callback(err);
dbquery('...', function(err, data_03) {
if (!! err) return callback(err);
callback(null, data_01, data_02, data_03);
});
});
});
}
ugly_nested(function(err, data01, data02, data03) {
if (!! err) throw err;
manage_data(data01, data02, data03);
});
The FOR loop is synchronous, but, the database calls are asynchronous, so, the for loop will end before the database returns his results. If you really need that for loop you can try out one of the nice flow control libraries out there
I am trying to use the async utility for the node.js. Below is my code. The console prints "In my func1" and "In my func2". I also expect it to print "call back func" but it won'nt
var myfunc1 = function(callback) {
var a = 1;
console.log ("In my func1");
};
var myfunc2 = function(callback) {
var b = 2;
console.log ("In my func2");
};
models.Picture.prototype.relativeSort = function(viewer_location) {
console.log("Rel Sort");
var sortedPics = [];
var relsortedPics = [];
// Finds all the pictures
async.series([myfunc1(), myfunc2()],
function(err, results){
if(err) {
throw err;
}
console.log("call back func");
return a+b;
});
};
You need to use the callback argument, for example:
var myfunc1 = function(callback) {
var a = 1;
console.log ("In my func1");
callback(null, 'test');
};
The first argument of callback is an error, and the second the result you want to pass to the final handler.
EDIT
I've missed the other mistake. This line:
async.series([myfunc1(), myfunc2()],
should be
async.series([myfunc1, myfunc2],
You are not supposed to call functions. You are telling async: "Hey, take these functions and do something (asynchronous) with them!".