Accessing a variable that is outside an anonymous function - javascript

I have this simple code
orm: function (req, res) {
// Send a JSON response
Noder.query('SELECT * FROM crud ', function(err, results) {
var all_rows = Noder.query('SELECT count(*) from crud ', function(err, the_rows) {
return the_rows;
});
res.view('noder/orm', {
layout: 'layout',
allr:all_rows,
post:results,
title: 'This is the hi page title. '
});
});
},
which i am using to fetch all rows in a mysql table. However inside that function,i want to have another function that counts how many rows there are in the table.My variable var all_rows shows me undefined when i try displaying it. How can i solve this?.

This is because you are accessing the value of all_rows before the inner-query has returned.
Noder.query is an asynchronous function, and as such, its execution will be delayed until the query itself is completed. Meanwhile, your orm function will continue merrily down and call res.view while your inner query is still processing.
To fix this, you can call res.view from inside your inner query.

Related

How to make object variable changes remain after ForEach loop. Javascript

I am trying to generate a Data object that I can use to create new documents in my MongoDB database using mongoose in NodeJS.
This is the snippet of code:
console.log(RecipeData.ingredients);
RecipeData.spices.forEach(function(spice){
module.exports.findSpiceByName(spice, function(err, res){
if (err){
return callback(err);
}
RecipeData.ingredients.push(res._id);
return callback(null, RecipeData);
});
});
console.log(RecipeData.ingredients);
basically, i have RecipeData that is a object with a few attributes. the main ones in this case is spice and ingredients. both of which are list of Strings.
I want to check RecipeData.spice:
if there is a element in the list: (the element would be the name of the spice)
I want to find the spice associated to that name in my Spices Collection and add its _id to my RecipeData.ingredients permanently
both the console.log's have the same output when they shouldn't in the example I am using to test this code.
Any idea why the variable RecipeData.ingredients is not changing outside the ForEach loop?
Thanks for any help in advance.
Sounds like an asynchronous programming issue. Though you didn't post the source, I'm assuming that module.exports.findSpiceByName is asynchronous, where forEach is not, so the forEach finishes and your second console.log runs before your findSpiceByName calls have time to complete.
One way to resolve this would be to use Promises and then wait for all of them to complete before trying to inspect the ingredients:
var spicePromises = RecipeData.spices.map(function(spice) {
return new Promise(function(resolve, reject) {
module.exports.findSpiceByName(spice, function(err, res) {
if (err) {
return reject(err);
}
resolve(res._id);
});
});
});
Promise.all(spicePromises).then(function(ingredients) {
Recipe.ingredients = ingredients;
console.log(RecipeData.ingredients);
});

Unable to access the variable in NodeJs function

I am using NodeJS postgresql client to fetch some data loop through it and give an output. I'm using ExpressJS together with postgresql client.
This is my code
var main_data = some array of data
var user_info = {}
for (var key in result.rows) {
var user = main_data[key].user
client.query('SELECT name,age,address FROM users WHERE user_id = $1 LIMIT 1;' , [user], function(queryErr, result){
var return_data = result.rows[0]
user_info.name = return_data.name
user_info.gender = return_data.gender
user_info.address = return_data.address
main_data[key].user_info = user_info
})
}
done()
res.json(main_data)
return
However when I run this code I don't get a proper output. The userinfo is not pushed to the main_data. It just outputs main_data variable just as the beginning of the code.
It is not simple as the suggested duplicate
Because the function sits inside a for loop so I can't just make the response call once the function is done. I have to wait till the whole loop is finished which may be 1000+ of loops to finish before I can make the response call.
So tell me how can I achieve it.
What am I doing wrong and how can fix it?
Thank you very much
I would use async.js for this, myself.
var rows = // your result.rows stuff.
function doTheQuery(item, callback){
// your query logic here, calling the callback with the results
}
async.series(rows, doTheQuery, function(err){
// handle any errors
}

Node/JSON Issues

So I am trying to figure out why my returned object every single time is just []?
Here is my code:
var returnObject = [];
db.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows)
{
console.log('Data: ', rows[i]);
var marker =
{
o_ID:rows[i].o_ID,
data:rows[i].data
};
returnObject[i]=marker;
console.log(chalk.red(returnObject[i].o_ID));
console.log(chalk.red(returnObject[i].data));
}
});
var sqsParams = {MessageBody: JSON.stringify(returnObject), QueueUrl :'---'};
For some reasons when I print the returnObject values they are correct but when it gets to the JSON.stringify something happens and sends to my SQS queue just [].
I thought maybe getting rid of the marker variable and just assigning
returnObject[i]= {
o_ID:rows[i].o_ID,
data:rows[i].data
};
But that still results in the same issue. Any ideas? Thanks!
Database queries in JavaScript are usually asynchronous. This means that the code inside your callback function function(err, rows, fields) will be run only after the database query has been done, whereas you assignment to sqsParams will be done right after the database query has been started. The result is that code inside your callback function has not been run before you returnObject with JSON.stringify and it is still in its original value [].
Your sqsParams variable is being set outside the db.query callback. As the db.query is asynchronous, your code is going to just fall through with an empty array.
Move your sqsParams variable into the callback you are supplying to db.query, eg:
console.log(chalk.red(returnObject[i].o_ID));
console.log(chalk.red(returnObject[i].data));
}
var sqsParams = {MessageBody: JSON.stringify(returnObject), QueueUrl :'---'};
// Use sqsParams here
});

Can't store result in session from async waterfall

I have a series of methods I run using async.waterfall which then return a result. I store that result into a request.session variable because I use Ajax and work with the result later on. However, I find that I can set the value of the session variable, but later on I cannot retrieve it.
Here's the code from the waterfall.
async.waterfall([
//Some functions
], function(err, result) {
request.session.cases = result;
response.render('template.jade', {
items : result
});
I then perform a jquery load to another url which then filters cases in request.session.cases.
But, I find that request.session.cases is undefined!
app.get('/case/:bugid', function(request, response) {
console.log(request.session.cases); //undefined
}
The weird part is that I can set request.session.cases to anything other than result (I can even set it to result[0]) and it will be fine. I've also printed out the value of result before I do the Ajax call and it is indeed populated with an array of objects.
cookieSession has a very small size of data that you can store into it. The data I was trying to store was too big for a cookieSession. Therefore I switched to using a session for that type of data, and using a normal cookie for user login.

How do I return the results of a query using Sequelize and Javascript?

I'm new at javascript and I've hit a wall hard here. I don't even think this is a Sequelize question and probably more so about javascript behavior.
I have this code:
sequelize.query(query).success( function(row){
console.log(row);
}
)
The var row returns the value(s) that I want, but I have no idea how to access them other than printing to the console. I've tried returning the value, but it isn't returned to where I expect it and I'm not sure where it goes. I want my row, but I don't know how to obtain it :(
Using Javascript on the server side like that requires that you use callbacks. You cannot "return" them like you want, you can however write a function to perform actions on the results.
sequelize.query(query).success(function(row) {
// Here is where you do your stuff on row
// End the process
process.exit();
}
A more practical example, in an express route handler:
// Create a session
app.post("/login", function(req, res) {
var username = req.body.username,
password = req.body.password;
// Obviously, do not inject this directly into the query in the real
// world ---- VERY BAD.
return sequelize
.query("SELECT * FROM users WHERE username = '" + username + "'")
.success(function(row) {
// Also - never store passwords in plain text
if (row.password === password) {
req.session.user = row;
return res.json({success: true});
}
else {
return res.json({success: false, incorrect: true});
}
});
});
Ignore injection and plain text password example - for brevity.
Functions act as "closures" by storing references to any variable in the scope the function is defined in. In my above example, the correct res value is stored for reference per request by the callback I've supplied to sequelize. The direct benefit of this is that more requests can be handled while the query is running and once it's finished more code will be executed. If this wasn't the case, then your process (assuming Node.js) would wait for that one query to finish block all other requests. This is not desired. The callback style is such that your code can do what it needs and move on, waiting for important or processer heavy pieces to finish up and call a function once complete.
EDIT
The API for handling callbacks has changed since answering this question. Sequelize now returns a Promise from .query so changing .success to .then should be all you need to do.
According to the changelog
Backwards compatibility changes:
Events support have been removed so using .on('success') or .success()
is no longer supported. Try using .then() instead.
According this Raw queries documentation you will use something like this now:
sequelize.query("SELECT * FROM `users`", { type: sequelize.QueryTypes.SELECT})
.then(function(users) {
console.log(users);
});

Categories

Resources