Node.JS - Node-PowerShell return value - node.js

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...

Related

How can I make the results of a csv file-to-multidimensional array available globally?

If I have a global array:
var people = [];
And I have the following function:
function readFile() {
var IN = require('ya-csv');
var filePath = 'data.csv';
var reader = IN.createCsvFileReader(filePath, {
'separator': ','
});
reader.on('data', function(item) {
people.push(item);
});
}
The people array only seems scoped inside reader.on. How can I use the people array globally?
Your code is perfectly right if the people variable is declared outside the readFile function, which seems to be the case.
I guess that your problem is something like this:
var people = [];
function readFile() {
var IN = require('ya-csv');
var filePath = 'data.csv';
var reader = IN.createCsvFileReader(filePath, {
separator: ',' // quotes around property name are optional
});
reader.on('data', function(item) {
people.push(item);
});
}
readFile();
console.log(people); // <- people is empty
This behaviour is absolutely normal. As ya-csv process incoming data asynchronously, you have to wait for processing to be finished.
That's the purpose of the end event, triggered by CsvReader when it has finished (unfortunately not documented on ya-csv documentation)
Refactoring like this will work better:
// make filePath a parameter, and use a callback function
function readFile(filePath, callback) {
// make people scoped to readFile()
var people = [];
var IN = require('ya-csv');
var reader = IN.createCsvFileReader(filePath, {
separator: ',' // quotes around property name are optional
});
// data is emitted for each processed line
reader.on('data', function(item) {
// closure magic: people is accessible because current function is nested into readFile()
people.push(item);
});
// end event
reader.on('end', function() {
// return results to caller, simply by invoking the callback.
// by convention, first argument is an error, which is null it no problem occured
callback(null, people);
});
// error handling
reader.on('error', function(err) {
// stop listening on events, to avoid continuing queuing data
reader.removeAllListeners();
// report to caller the error.
callback(err);
}
}
readFile('data.csv', function(err, results) {
if (err) {
// error handling
return ...
}
// nominal case: use results that contains peoples !
console.dir(results);
});
Please ask question with comments if something is not clear.
== EDIT ==
Alternatively, you can use a variable outside readFile()
// notice: people is declared outside readFile
var people = []
// make filePath a parameter, and use a callback function
function readFile(filePath, callback) {
var IN = require('ya-csv');
var reader = IN.createCsvFileReader(filePath, {
separator: ',' // quotes around property name are optional
});
// data is emitted for each processed line
reader.on('data', function(item) {
// closure magic: people is accessible because current function is nested into readFile()
people.push(item);
});
// end event: directly invoke callback
reader.on('end', callback);
// error handling
reader.on('error', function(err) {
// stop listening on events, to avoid continuing queuing data
reader.removeAllListeners();
// report to caller the error.
callback(err);
}
}
readFile('data.csv', function(err) {
if (err) {
// error handling
return ...
}
// you cannot use people before here, because you have no garantie that read process is finished.
console.dir(people);
});
The drawback of this code is that calling readFile() multiple times will enqueue in the same variable, which is not modular nor reliable.

How to set a variable to a query? mongodb

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.

How to add an array of objects to parse.com db?

I'm developing an application and need to add many items at a time.
How can I do that with node.js?
This is the npm module for parse.com but there is no method like
insertAll("Foo", [objs...], ...)
I don't want to insert single object every time.
Write a convenience function that interfaces between your application and parse.com. You will have to write the iteration code once (or debug mine)
var async = require('async');
var parseApp = require('node-parse-api').Parse;
var APP_ID = "";
var MASTER_KEY = "";
var parseApp = new Parse(APP_ID, MASTER_KEY);
function insertAll(class, objs, callback){
// create an iterator function(obj,done) that will insert the object
// with an appropriate group and call done() upon completion.
var insertOne =
( function(class){
return function(obj, done){
parseApp.insert(class, obj, function (err, response) {
if(err){ return done(err); }
// maybe do other stuff here before calling done?
var res = JSON.parse(response);
if(!res.objectId){ return done('No object id') };
done(null, res.objectId);
});
};
} )(class);
// async.map calls insertOne with each obj in objs. the callback is executed
// once every iterator function has called back `done(null,data)` or any one
// has called back `done(err)`. use async.mapLimit if throttling is needed
async.map(objs, insertOne, function(err, mapOutput){
// complete
if(err){ return callback(err) };
// no errors
var objectIds = mapOutput;
callback(null, objectIds);
});
};
// Once you've written this and made the function accessible to your other code,
// you only need this outer interface.
insertAll('Foo', [{a:'b'}, {a:'d'}], function(err, ids){
if(err){
console.log('Error inserting all the Foos');
console.log(err);
} else {
console.log('Success!);
};
});

how to wait the end of the execution of a function

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/

nodejs- callback in modules not working

I am performing database connection in nodejs module. But its callback is not called.
Here is my module-
*getChapterList.js
var mysql=require('mysql');
var client=mysql.createClient({
user:'mysql',
password:''
});
client.useDatabase('test');
module.exports.get_chapter_list = function(subject_id){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
return results;
});
return "hello";
};
Now i am calling this module as-
rs=require('./getChapterList');
rs.get_chapter_list(1);
// Output: hello
but expected o/p is results array.
Googled alot.but no result..
The callback will be called after the query completes and the return value of results will be passed back to the method that created the callback, which then discards it.
The reason why the output is "hello", is because that's what the get_chapter_list function returns.
What happens is:
You call the get_chapter_list function
The client.query fires off a request to the database
The client.query function returns.
The get_chapter_list function returns "hello".
The SQL query completes and calls the callback
Your callback method is called and does nothing (it just returns the results, but that return value is handed back to the caller of the callback (somewhere within client.query) which discards it).
To get what you want you'll probably need to think asynchronously.
Define the method as
module.exports.get_chapter_list = function(subject_id, callback){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
// doesn't contain any error handling
callback(results);
});
};
and then call the method:
rs.get_chapter_list(1, function(results) {
console.log(results); // or whatever you need to do with the results
});
You need to return the results asynchronously:
exports.get_chapter_list = function(subject_id, callback) {
client.query("select ...", callback);
};
...
var rs = require('./getChapterList');
rs.get_chapter_list(1, function(err, results) {
if (err) {
// handle error
} else {
// do something with results
console.log(results);
}
});
scttnlsn answer is correct, as I have faced this issue and had solved by just passing the callback function as a argument.
Try for that:
var mysql=require('mysql');
var client=mysql.createClient({
user:'mysql',
password:''
});
client.useDatabase('test');
module.exports.get_chapter_list = function(subject_id, callback){
client.query("select distinct chapter_id from course_associations where subject_id="+subject_id+" and status_id=1",
function(err,results,fields){
callback( results );
});
return "hello";
};
And then
var rs = require('./getChapterList');
rs.get_chapter_list(1, function(results) {
console.log(results);
}
});
This will print the desire output.

Resources