How to properly export/require - node.js

I'm trying to export one function this way:
exports.query = function(request){
conn.query(request, function(err, rows, fields){
if(err) console.log(err);
return rows[0].id;
});
}
and using it:
var mysql = require('./mysql');
console.log(mysql.query('SELECT * FROM tablename'));
Proceeding this way for getting a result involves undefined as output.
How do I to fix this, please?
Note that when I just type console.log(rows[0].id) instead of return rows[0].id it sends back 123.
Thanks in advance!

In your example, the output is being returned to the anonymous function of the database query instead of the caller of the module. You can use a callback to return output to the caller of the module.
exports.query = function(request, callback){
conn.query(request, function(err, rows, fields){
if (err) {
callback(err);
} else {
callback(null, rows[0].id);
}
});
}
Then call it like
var mysql = require('./mysql');
mysql.query('SELECT * FROM tablename', function(err, results){
if (err) {
console.error(err);
} else {
console.log(results);
}
});

That's a problem of synchrony.
the conn.query function returns undefined because it finish its execution before the results are fetched (like almost any i/o related operation on js/node).
One possible solution to that, is to provide a callback to your query function.
exports.query = function(request, cb){
conn.query(request, function(err, rows, fields){
// some "special" processing
cb(err, rows, fields);
});
};
If you're not familiar with async functions, take a look on some articles about that:
http://justinklemm.com/node-js-async-tutorial/
https://www.promisejs.org/

Related

AWS Lambda query with async waterfall in node.js 8.10

I send two query sequentially
Query the data from A tables, and then accoring to the result, query the data from B table.
So, I query the data like that,
var async = require('async');
var mysql = require('mysql');
var config = require('./config.json');
var connection = mysql.createConnection({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
// TODO implement
var tasks = [
function (callback) {
connection.query("SELECT email FROM Visitor WHERE id =?;", [1], function (err, row) {
if (err) return callback(err);
if (row.length == 0) return callback('No Result Error');
callback(null, row[0]);
})
},
function (data, callback) {
connection.query("SELECT id,signtime FROM Board WHERE email =?;", data.email, function (err, row) {
if (err) return callback(err);
if (row.length == 0) {
return callback('No Result Error');
}else {
callback(null, row[0])
}
})
}
];
async.waterfall(tasks, function (err, result) {
if (err)
console.log('err');
else
***return result;***
console.log('done');
connection.end();
});
};
I log the data with console.log(), it take the data in command line.
But in lambda, put the function into exports.handler, it response null.
If I change the 'return result' to callback(result), it occurs error.
I think it maybe too simple to solve this problem
If you know about that, please help me
In the first case, response is null because you didn't use neither Promise, nor callback to let the Lambda sandbox know that the job is done. In the second case, you used the callback, but you passed the result as the first argument to it. Lambda programming model for Node.js follows a principle called "error first callback". Long story short, if any error occurred during execution, you should go with callback(error), and if everything is ok and you need to return some result from lambda, you should go with callback(null, result). So basically on your line before console.log('done'); use callback(null, result) and it will work for you.

Node.js async map over MongoDB queries

I'm having a problem with async Node.js module. In my Node.js app, I'm trying to get an array of JSON objects returned by a MongoDB request:
var fruits = ["Peach", "Banana", "Strawberry"];
var finalTab = [];
fruits.forEach(function(fruit) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
finalTab[fruit] = result;
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
}));
});
console.log(finalTab); // -> []
At the moment, I'm at this point.
I'm trying to implement the async.map to iterate through Fruits collection.
https://caolan.github.io/async/docs.html#map
Can someone help? :)
Thanks by advance for help.
EDIT:
As I need all results returned by my db.collection functions, I'm trying to add these async commands to a queue, execute it and get a callback function.
You can try this:
async.map(fruits , function (fruit, callback) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
//here you are assigning value as array property
//finalTab[fruit] = result;
// but you need to push the value in array
finalTab.push(result);
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
//callback once you have result
callback();
}));
}.bind(this), function () {
console.log(finalTab); // finally call
}, function (err, result) {
return Promise.reject(err);
});

what is the benefit to using mongoose .exec?

User.find().exec(function (err, users) {
if (err){
callback(err);
} else {
callback(users);
}
});
User.find(function (err, users) {
if (err) {
callback (err);
} else {
callback(users);
}
});
What is the benefit of using the top code? both seem to work equally well
They are identical and there's no benefit in your example
When you do not pass a callback to find function it won't execute but instead returns a query then you need to use exec()
var query = User.find();
now you can add some more criteria
query.where({age: 15});
and some more
query.select({name:1}); // or {firstname:1, lastname:1} etc.
now you've built up your query so to get the results you need to execute it.
query.exec(function(err, users){
});
But you can also do this like
User.find({age:15}, {name:1}, function(err, users){
});
Above is identical to
User.find({age:15}, {name:1}).exec(function(err, users){
});
since there's no callback in find function it will return query which means no results, exec will give you the results

Async node.js data flow confusion

thanks for your help...struggling big time with how to handle this properly. I'm in async now, having given up on my ability to write the callbacks properly. I have snippet where I'm passing a set of random numbers (eachrecord) and passing them through to a mongoose call. Trying to create a data set from the multiple queries I pass.
My issue is that no matter what I've done for 4 hours, the "newarray" variable is always empty.
Thank you for your help -
async.forEach(arLimit, function(eachrecord, callback){
newarray = new Array;
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
console.log(err);
else {
newarray.push(data);
}
});
callback(null, newarray);
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
There are several issues with your code:
async.forEach isn't meant to 'generate' results, that's what async.map is for;
you need to call the callback only when execFind is done, and not immediately after calling it;
your newarray is probably not necessary;
So try this instead:
async.map(arLimit, function(eachrecord, callback){
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
callback(err); // pass error along
else {
callback(null, [ data ]);
// although I think you mean this (because 'data' is probably an array already)
// callback(null, data);
}
});
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});

Return value from nested callback instead of the parent function

I have a parent function which has multiple callbacks and need to pass the result of the innermost callback to the function which calls this "parent" function. As NodeJS is asynchronous, my parent function obviously always returns before the callbacks are executed.
How can I make my callbacks return to the caller?
Code example that I am using right now -
var addNewUser = function(hash,name,number,time,syncTime){
// check here if the user exists or not by querying the phone number first
connection.query('SELECT user_id FROM users WHERE user_phone_number ="' +number+'"',function(err,rows,fields){
if(rows[0]) return false;
connection.query('INSERT INTO users (authorization_hash,user_name,user_phone_number,user_local_time,is_active,last_synced) VALUES ("'+hash+'","'+name+'","' + number+'","' +time+'","1","'+syncTime+'")',function(err,rows,fields){
if(err) throw err;
return true;
});
});
}
I Want to be able to return this callback return to the caller function.
Have addNewUser accept a callback as its last argument and have the innermost function call the callback with the value.
Alternatively, you could look into having addNewUser return a promise. RSVP or Q are implementations of the Promises/A :
function addNewUser(hash,name,number,time,syncTime) {
var deferred = Q.defer();
connection.query("SELECT ...", function(err, rows, fields) {
if(err) { deferred.reject(err); }
if(rows[0]) { deferred.reject("some reason"); }
connection.query("INSERT INTO ...", function(err, rows, fields) {
if(err) { deferred.reject(err); }
deferred.resolve(rows[0]); // Whatever addNewUser would return normally
});
});
return deferred.promise;
}
Then the caller would use it like this:
addNewUser(...).then(function(newUserAdded) {
// Do something with newUserAdded here
}, function(err) {
// Do something with the error here
});

Resources