Using node-mysql in a function - mysql

I'm very new to nodejs and have a question.
Trying to create a function that will call the value of any field where I mention its ID from a table:
function getUserInfo (userID, dynamicField) {
var query = connection.query('SELECT '+dynamicField+' from users WHERE userID = '+connection.escape(userID));
query.on('result', function(row) {
return(row.dynamicField);
});
};
console.log(getUserInfo(8, userEmail)) //this should get me the userEmail value of the user with userID=8
However, I get "undefined". If I use console.log rather than return, it logs the value but this has no use as a function to be used inside other functions to get a value.
I will be glad if I can get help for modifying the function.

This is a common mistake amongst async/nodejs beginners. You have essentially wrapped an async function inside a sync function which breaks down the nature of node's event loop. The return expression needs to be replaced with a callback. See below:
// Method
function getUserInfo (userID, dynamicField, callback) {
var query = connection.query('SELECT '+dynamicField+' from users WHERE userID = '+connection.escape(userID));
query.on('result', function(row) {
callback(null, row.dynamicField);
});
};
// Implementation
getUserInfo(8, userEmail, function(err, result){
console.log(err || result);
});
By convention, in Nodejs we always pass an error object first in the callback. In this case since there is no error to capture, we pass null in its place.

Related

How do I call a variable from a function in nodejs?

In the following code I want to call payment_amount outside of the function, I've tried declaring the variables with var to make them global variables, but I still can't seem to call them outside of the function.
var payment_amount;
con.query("SELECT payment_amount FROM transactions LIMIT 1",function(err,payment_amount,fields){
if(err)throw err;
payment_amount = JSON.stringify(payment_amount);
payment_amount = payment_amount.replace('[{"payment_amount":','');
payment_amount = payment_amount.replace('}]','');
payment_amount = parseFloat(payment_amount);
console.log(payment_amount);
return payment_amount;
});
console.log(payment_amount); //RESULTS IN 'UNDEFINED'
Your con.query() call is likely asynchronous. That means that you're getting to the console.log() before the function inside the .query() callback is completed. Here are some docs that generally outline how asynchronous code works in JS: Async docs
What ORM are you using to get to the database? You can usually find examples on how to use async/await for that ORM. The call might end up looking something more like...
const getPaymentAmount = async () => {
try {
const paymentAmountResult = await con.query("SELECT payment_amount FROM transactions LIMIT 1")
console.log(paymentAmountResult) // works!
///... your parsing code etc.
return thingYouWantToReturn
} catch (err) {
throw new Error(err);
}
}

How to use callbacks in module.export function for mysql query - nodejs,express

I have the following code structure in exports.js
module.exports = {
getData:function(param1,param2,callback){
sql.query('SELECT users FROM table',function(error,result){
callback(null,result[0]);
});
}
}
And I called it from main file app.js file like
var common = require('./exports');
console.log(common.getData(null,null));
I got the following error
TypeError: callback is not a function
However I found a similar question here. But didn't fixed the problem. Any help would be appreciated..!
if you want print results
var common = require('./exports');
common.getData(null, null, function(err, result){
console.log(result)l
})
getData() accepts 3 arguments
The last of which should be a function which you have not provided in your example. Add a callback function in your call like so:
common.getData(null,null, function(err, result) {
console.log(result)
});
The sql.query function uses the callback function you pass in as the third parameter and thats why your getting the error to say it's missing.

synchronous mysql queries in nodejs

I'm pretty new to nodejs and I'm having some difficulties to understand how to use the mysql connection object.
My problem is not in the code but in the design pattern.
lets say I have a user module
module.exports = function(){
return{
id: "",
load: function(id){
var sql = 'SELECT * from users where id = '+ DB.escape(id);
console.log(1);
DB.query(sql, function (err, rows) {
this.id = rows[0].id; // not working
console.log(rows[0].id); // prints the id 4
console.log(2);
});
console.log(3);
}
}
}
from outside the module i run the next code
var user = require('../modules/user');
var selected_user = user();
console.log("entering users me route");
selected_user.load(4);
console.log("user id is " + selected_user.id); //This does not print the id 4
when I run the code, the console logs 1, then 3, and then 2.
This is due to the asynchronous flow of node js.
But if I'm building a website, and I need the query to end in order to populate my user object before I send the HTML to the browser???
What's the right way to do it ?
Also when I try to populate the id property of user in the id i receive from the DB it does not work.
Any ideas?
Thanks
There are several ways to do this. I would go with Promises.
Suppose you have an asynchronous function "getUsers".
It looks like this:
function getUsers() {
longQuery(function(err, result){
// What to do with result?
});
You need to rewrite it to be able to use the result.
Let's try:
function getUsers() {
return new Promise(function(resolve, reject) {
longQuery(function(err, result){
if(err) reject(err)
else resolve(result)
});
});
Now this function returns a promise. What do we do with that promise?
function handleRequest(req, res) {
getUsers().then(function(result) {
// Do stuff with result
res.send(myProcessedData);
}).catch(function(err) {console.log(err)};
}
This could also have been done with callbacks, passing the response object as a parameter to the query function, and many other ways, but I think promises are a very elegant way for handling this.
this.id = rows[0].id; // not working
The above line is not working because you are setting it to this.id from inside a callback function. When you are inside a callback function this does not mean the this in the main object.
For more discussion about this: see How to access the correct `this` context inside a callback?
To tackle the asynchronous nature of javascript you can either use promise like the answer from matanso or you can pass a callback function to your load method. So your load: function(id) method will be load: function(id, callbackFunction) and call the callback function when you get all the data that you need.

Mongoose Populate with express res.json() breaks

So I'm selecting Activities from the mongodb and populating User for each.
var query = Activity.find(query).populate("user");
return query.sort({created:"desc"}).exec(function(err, activities) {
debugger;
if (!err) {
return res.json(activities);
} else {
res.status(400).json(err);
}
});
As you can see I have a debugger; breakpoint is there, When I'm pring activities it prints an array of activities with the user object populated.
Also when I'm calling something like activities[0].toJSON() I get everything good!
But the response comes back with the user property empty !
I looked into the source of express.response.json(OBJ) and saw this line:
var body = JSON.stringify(val, replacer, spaces);
val is my activities
When calling JSON.stringify(activities) it will create a json with an empty user field.. any suggestions ?
Try the lean option. That gives back plain JS objects with no mongoose weirdness. Also, your error handling seems a little awkward, can be simplified.
var query = Activity.find(query).populate("user");
query.sort({created:"desc"}).lean().exec(function(err, activities) {
if (err) return res.status(400).json(err);
res.json(activities);
});
I would go even further, not hard-coding error sending in routes but simply passing along via if (err) return next(err) to error-handling middleware defined elsewhere in your app. You can still set the status, then use detection in your middleware, something like this:
app.use(function(err, req, res, next){
err.status = err.status || 500;
res.status(err.status).json(err);
});

Simple Express program for querying a result

I have a snippet of Express code
Below what i am trying to do is pass the table name to keyName by extracting from the request
But I am facing deaslock
i wanted to know whether i am following proper protocols for JSON response
[Part-of-Express-Code]
app.get('/RestaurantDesc/:Key',function(request,response,next){
var keyName=request.query.Key;
var name_of_restaurants, RestaurantTimings;
async.series( [
// Get the first table contents
function ( callback ) {
connection.query('SELECT * FROM ',keyName, function(err, rows, fields)
{
console.log('Connection result error '+err);
name_of_restaurants = rows;
callback();
});
},
// Get the second table contents
function ( callback ) {
connection.query('SELECT * FROM RestaurantTimings', function(err, rows, fields)
{
console.log('Connection result error '+err);
RestaurantTimings = rows;
callback();
});
}
// Send the response
], function ( error, results ) {
response.json({
'restaurants' : name_of_restaurants,
'RestaurantTimings' : RestaurantTimings
});
} );
} );
I am getting the output as Cannot GET /RestaurantDesc/
Any Ideas
your route should be path, A path that you can access through GET request.
for ex: you should be able to access it through
http://example.com/RestaurantDesc/anyKeyHere
and in your code you have
var keyName = request.query.Key
req.query contains query variables see http://expressjs.com/api.html#req.query
So your keyName variable won't contain anyKeyHere.
req.params.Key will contain value anyKeyHere;
but you will need to pass it in url path.
if you need to pass key data in query you can do this.
app.get('/RestaurantDesc',function(request,response,next){
var keyName=request.query.Key;
});
and pass key like this in your url
http://example.com/RestaurantDesc/?Key=restaurnetkeyHere
Try going through guide in express site and understand routings and how it works.
If you getting "Cannot GET /RestaurantDesc/" is because you have not setup this route, try /RestaurantDesc/something. request.query is used for search terms, ie things that come after a questionmaek in a url. Use request.param.Key instead.
Also for best practices you should lowercase resource names and use the shorter req/res instead of request/response.