I'm using mssql(Microsoft SQL Server client for Node.js) package from npm.I'm trying to execute a stored procedure residing in my sql server database.Everything works fine.However what I want to do is return the recordsets so that i can export this to be used in other module.Below is what I'm trying to do.
function monthlyIceCreamSalesReport (scope){
var connObj = connConfig();
connObj.conn.connect(function(err){
if(err){
console.log(err);
return;
}
connObj.req.input('Month',4);
connObj.req.input('Year',2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue){
if(err){
console.log(err);
}
else {
console.log(recordsets[0]); // successfully receiving the value
}
connObj.conn.close();
});
});
console.log('check for recordsets', recordsets[0]); // undefined
return recordsets[0];
}
var sqlServerObj = {
monICSalesReport : monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;
As shown in the code snippet, since the value of recordsets[0] is undefined, exporting this function is of no use.
You can't return this way in async nature. You can get it by passing the callback function
Try to give a callback function like this
function monthlyIceCreamSalesReport(scope, callback) { // pass a callback to get value
var connObj = connConfig();
connObj.conn.connect(function(err) {
if (err) {
console.log(err);
return;
}
connObj.req.input('Month', 4);
connObj.req.input('Year', 2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue) {
if (err) {
console.log(err);
} else {
console.log(recordsets[0]);
connObj.conn.close();
return callback(null, recordsets[0]); //return as a callback here and get that value in callback from where you called this function
}
});
});
}
var sqlServerObj = {
monICSalesReport: monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;
Note: See the comment to understand the changes
recordsets[0] is undefinded, because is defined only in connObj.req.execute function scope. You may do this in this way:
function monthlyIceCreamSalesReport (scope, cb){
var connObj = connConfig();
connObj.conn.connect(function(err){
if(err){
console.log(err);
return cb(Error("Something wrong"));
}
connObj.req.input('Month',4);
connObj.req.input('Year',2016);
connObj.req.execute('<myStoredProcedure>', function(err, recordsets, returnValue){
if(err){
console.log(err);
connObj.conn.close();
return cb(Error("Something wrong"));
}
else {
console.log(recordsets[0]); // successfully receiving the value
connObj.conn.close();
return cb(recordsets[0]);
}
});
});
}
var sqlServerObj = {
monICSalesReport : monthlyIceCreamSalesReport,
};
module.exports = sqlServerObj;
Related
As we know, we must return the response in the express app to avoid "Cannot set headers after they are sent to the client" error.
However, In below code, I'm trying to return the response but It's returning to our router and causes mentioned error. how I can directly return the response in function?
router.post("/admins", async function (req, res) {
var newAdminObj = await newAdminObjectDecorator(req.body, res);
var newAdmin = new Admins(newAdminObj)
newAdmin.save(function (err, saveresult) {
if (err) {
return res.status(500).send();
}
else {
return res.status(200).send();
}
});
});
// the function
var newAdminObjectDecorator = async function (entery, res) {
// doing some kinds of stuff in here
// if has errors return response with error code
if (err) {
// app continues after returning the error header response
return res.status(500).send();
}
else {
return result;
}
}
Never run a response operation other than the controller's functions. Let the other function return the answer and decide according to the answer.
router.post("/admins", async function (req, res) {
var newAdminObj = await newAdminObjectDecorator(req.body);
if (newAdminObj instanceof Error) {
return res.status(500).send()
}
var newAdmin = new Admins(newAdminObj)
newAdmin.save(function (err, saveresult) {
if (err) {
return res.status(500).send();
}
else {
return res.status(200).send();
}
});
});
// the function
var newAdminObjectDecorator = async function (entery) {
// doing some kinds of stuff in here
// if has errors return response with error code
if (err) {
// app continues after returning the error header response
return err;
}
else {
return result;
}
}
getting undefined all the time "main.js":
var dbAccess = require('../dao/dbAccess');
dbaInstance = new dbAccess();
var wordPool = dbaInstance.getWordPool();
console.log (wordPool);
and "dbAccess.js" contains:
var DatabaseAccess = function() {}
DatabaseAccess.prototype.getWordPool = function () {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
//console.log(wordPoolFromDB); -working ok
return (wordPoolFromDB);
});
}
module.exports = DatabaseAccess;
why is it not working?
DatabaseAccess.prototype.getWordPool is not returning any result.
Since you are using an asynchronous function, you need do one of these things:
a) Take a callback as parameter and invoke the callback with a result
DatabaseAccess.prototype.getWordPool = function (cb) {
RoundWord.find({}, 'words decoys', function(err, results) {
if (err) {
return cb(err, null);
}
cb(null, results);
});
}
The callback convention is: cb(error, results...)
b) Use promises
DatabaseAccess.prototype.getWordPool = function () {
return RoundWord.find({}, 'words decoys', function (err, results) {
if (err) {
throw err; // however you might want to sanitize it
}
return results;
});
}
To consume this result you will need to do it as a promise
databaseAccess.getWordPool()
.catch(function (err) {
// process the error here
})
.then(function (results) {
// something with results
});
It will work if you change to this:
var dbAccess = require('../dao/dbAccess');
dbaInstance = new dbAccess();
dbaInstance.getWordPool(function(wordPool){console.log (wordPool);});
And:
var DatabaseAccess = function() {}
DatabaseAccess.prototype.getWordPool = function (cb) {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
//console.log(wordPoolFromDB); -working ok
cb(wordPoolFromDB);
});
}
module.exports = DatabaseAccess;
If the function is Asynchronous you need to pass a callback to find to get the result:
DatabaseAccess.prototype.getWordPool = function (callback) {
RoundWord.find({},'words decoys', function(err, wordPoolFromDB) {
if (err) throw err;
callback(err, wordPoolFromDB);
});
}
and call it as follows in main:
dbaInstance.getWordPool(function (err, wordPool) {
console.log (wordPool);
// wordPool is only available inside this scope,
//unless assigned to another external variable
});
// cannot access wordPool here
I am creating a service in sails js. I want to update the value of totalCount before returning it. But the problem is when the return is in the callback of the async.series I am getting an undefined when I'm invoking it. How should I do this?
var totalCount = 0;
async.series([
function getProducts(cb_series){
Inventory.find({sku_id : sku_id, bay_id : bay_id})
.then(function(inventory_items){
async.each(inventory_items, function(item, cb_each){
totalCount = totalCount + item.physical_count;
cb_each();
}, function(err){
if(err)
console.log(err);
cb_series();
});
});
}
], function returnResult(err, cb){
if(err)
console.log(err);
return totalCount;
});
I'm not totally sure what you're trying to do. But you probably want to pass totalCount out in a callback like this:
function getProducts(callback){
Inventory.find({sku_id : sku_id, bay_id : bay_id}).then(
function(inventory_items){
callback(null, inventory_items.length)
}, function(err){
console.log(err);
callback(err);
});
}
If there is an error, it will call back with the error as it's first parameter, so do a null check on that. If the first parameter is null, then the second parameter will be the length of your array.
If you'd rather return all of the products and not just the length (as the name of the function implies), then it's very similar:
function getProducts(callback){
Inventory.find({sku_id : sku_id, bay_id : bay_id}).then(
function(inventory_items){
callback(null, inventory_items)
}, function(err){
console.log(err);
callback(err);
});
}
You'd use it like this for the first case:
getProducts(function(err, productCount) {
if(err) {
console.log(err);
return err;
} else {
var totalCount = productCount;
}
//etc etc...
}
...or this for the second case:
getProducts(function(err,products) {
if(err) {
console.log(err);
return err;
} else {
var productArray = products;
}
//etc etc...
}
Is there a better way to call the same function from the client and another node js module. Without having 2 separate functions. The only difference method the value is returned?
exports.getFiles = function(req,res){
var globPattern = req.body.globPattern;
var globOptions =req.body.globOptions;
glob(globPattern, globOptions, function (err, files) {
if(err)
{
res.status(400);
winston.log('error', err);
return res.send({success:false,reason: err});
}
res.send({success:true,data:files});
});
};
exports.getFilesFunc = function(payload){
var deferred = q.defer();
var globPattern = payload.globPattern;
var globOptions = payload.globOptions;
glob(globPattern, globOptions, function (err, files) {
if(err)
deferred.resolve({success:false,reason: err});
deferred.resolve({success:true,data: files});
});
return deferred.promise;
};
You can basically call getFilesFunc from getFiles:
exports.getFilesFunc = function(payload){
return Q.nfcall(glob, payload.globPattern, payload.globOptions);
};
exports.getFiles = function(req,res){
this.getFilesFunct(req.body).then(function(files) {
res.send({success:true, data:files});
}, function(err) {
res.status(400);
winston.log('error', err);
return res.send({success:false, reason: err});
});
};
Since you're using Promises, you can shorten your code to the following:
var Q = require('q'),
glob = Q.denodeify(require('glob'));
exports.getFiles = function(pattern, options) {
return glob(pattern, options);
};
Then in your controller, or wherever you're calling the function you'd control what you're going to do with your retured data:
module
.getfiles(req.body.globPattern, req.body.globOptions)
//or .getFiles(payload.globPattern, payload.globOptions)
.then(function (files) {
}, function (error) {
});
I am new to node, and also JavaScript callbacks.
I am trying to check if an account exists in mongo and then 'save it' if it doesn't and return an error if it does.
I am currently trying to figure this out outside of my express app. This is what i have..
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/main', function (err, db) {
if(err) throw err;
var query = { name : "www.website.com"}
findOne(db, query, function (doc) {
if(doc) {
console.log('account exists');
} else {
console.log('good to go');
}
console.dir(doc);
});
});
var findOne = function (db, query, callback) {
db.collection('accounts').findOne(query, function (err, doc) {
if(err) throw err;
db.close();
callback();
});
}
with the console.dir(doc); above returning as undefined. How do I wait for the findOne to return before using the callback to console.log or save the account?
The reason you are getting undefined is because when you call your callback your are not passing it the doc. That line should look like callback(doc).
Here is an updated version of your code with a few suggestions:
MongoClient.connect('mongodb://localhost:27017/main', function (err, db) {
if(err) throw err;
var query = { name : "www.website.com"}
findOne(db, query, function (err, doc) {
if(err) {
// something went wrong
console.log(err);
return;
}
if(doc) {
console.log('account exists');
console.dir(doc);
} else {
console.log('good to go');
}
});
});
var findOne = function (db, query, callback) {
db.collection('accounts').findOne(query, function (err, doc) {
db.close();
if(err) {
// don't use throw when in async code
// the convention is to call your callback with the error
// as the first argument (notice that I added an argument
// to the definition of your callback above)
callback(err);
}
else {
// call your callback with no error and the data
callback(null, doc);
}
});
}