How to make object while in for loop using node-mysql? - javascript

I have "for" loop in a function and I want to make 1 object instead of many to save draw calls. Is there any way I could do that ? On my tests I have find out that I can't make var outside connection.query which would contain data from what query. So I can't even use global variable which is contained in that query. I am new on this so any help would be great.
External file included in app.js
load_sent_mail: function(person_id, callback, socket) {
pool.getConnection(function(err, connection) {
connection.query('SELECT * FROM `mail` WHERE mail_sender = ' + person_id + '', function(err, mail_data) {
if (!err) {
for (var key in mail_data) {
var items_to_get_info = [];
if (mail_data[key].mail_spot_1 != 0) items_to_get_info.push(mail_data[key].mail_spot_1);
if (mail_data[key].mail_spot_2 != 0) items_to_get_info.push(mail_data[key].mail_spot_2);
if (mail_data[key].mail_spot_3 != 0) items_to_get_info.push(mail_data[key].mail_spot_3);
if (mail_data[key].mail_spot_4 != 0) items_to_get_info.push(mail_data[key].mail_spot_4);
if (items_to_get_info.length) {
connection.query('SELECT `person_items`.`id`, `items`.`item_image`, `items`.`item_place` FROM `person_items` INNER JOIN `items` ON `person_items`.`item_id` = `items`.`item_id` WHERE `person_items`.`id`IN (' + items_to_get_info.join(",") + ')', function(err, items_in_mail) {
if (!err) {
callback(null, items_in_mail);
} else {
console.log(err)
}
});
} {
//0 items
}
}
}
})
connection.release();
});
}
app.js
mail.load_sent_mail(person_id,function(err,items_in_mail){
socket.emit('incoming_mail', items_in_mail);
});

If I understand your question correctly, does this solve your problem:
load_sent_mail: function(person_id, callback, socket) {
pool.getConnection(function(err, connection) {
connection.query('SELECT * FROM `mail` WHERE mail_sender = ' + person_id + '', function(err, mail_data) {
if (!err) {
// Move this line before the loop
var items_to_get_info = [];
for (var key in mail_data) {
if (mail_data[key].mail_spot_1 != 0) items_to_get_info.push(mail_data[key].mail_spot_1);
if (mail_data[key].mail_spot_2 != 0) items_to_get_info.push(mail_data[key].mail_spot_2);
if (mail_data[key].mail_spot_3 != 0) items_to_get_info.push(mail_data[key].mail_spot_3);
if (mail_data[key].mail_spot_4 != 0) items_to_get_info.push(mail_data[key].mail_spot_4);
}
// Move this line after the loop
if (items_to_get_info.length) {
connection.query('SELECT `person_items`.`id`, `items`.`item_image`, `items`.`item_place` FROM `person_items` INNER JOIN `items` ON `person_items`.`item_id` = `items`.`item_id` WHERE `person_items`.`id`IN (' + items_to_get_info.join(",") + ')', function(err, items_in_mail) {
if (!err) {
callback(null, items_in_mail);
} else {
console.log(err)
}
});
}
}
})
connection.release();
});
}
I think I lost a bracket somewhere, but I hope you get the idea!

Related

how to call an array which is in a function from the another function in javascript?

This is the async function:
async function getpackages(conn, childId, callback) {
var childId = childId;
var request6 = new sql.Request(conn);
var packageQuery = "select OrderId,ChildID from dbo.tbl_Scheduler where NoOfMealsLeft>0 and ChildId=" + childId;
await request6.query(packageQuery, function (err, packagelist) {
if (!err && packagelist.recordsets.length > 0) {
console.log("Error:" + err + "Result:" + util.inspect(packagelist.recordsets[0]));
var orderdetail_ = [];
for (i = 0; i < packagelist.recordsets[0].length; i++) {
orderdetail_.push(packagelist.recordsets[0][i].OrderId);
}
console.log("-->" + orderdetail_);
callback(null, packagelist.recordsets[0]);
} else if (packagelist.recordsets.length < 1) {
callback("Not a valid id input", null);
}
});
};
I need to call the orderdetails_ array in the query. The array contains four data and I need to iterate over 4 data one by one, using the or in the SQL query.
module.exports.newscheduledmeal = function (req, res, next, callback) {
let entered_date = req.query.date;
let childId = req.query.id;
let current_date = new Date().toISOString().slice(0, 10);
if (entered_date < current_date) {
return callback('Please enter date more than or equal to current date.', null);
} else
var conn = new sql.ConnectionPool(dbConfig);
try {
conn.connect().then(function () {
var request = new sql.Request(conn);
getpackages(conn, childId, function (err, orderid) {
if (err) {
callback(err, null);
} else
var PackageidQuery = "select PackageId from dbo.tbl_Order where OrderId=";
request.query(PackageidQuery, function (err, packagelist) {
if (!err) {
conn.close();
callback(null, packagelist.recordsets);
} else {
conn.close();
callback("Error", null);
}
});
});
});
} catch (err) {
console.log("Exception occured:" + err);
conn.close();
callback(err, null);
}
};
I want to get the details of the array which is in getpackages to be used in the module section and specifically in the SQL query section.

How to run code only after query has finished?

I have the following code:
var userFound = false;
let sql = `SELECT box_id, cubby_id, comport, deliveredToUser
FROM recipients
WHERE package_password = ?`;
connection.query(sql, [req.session.sessionUserPackagePassword],
function(err, rows, fields) {
if (!err) {
for (var i = 0; i < rows.length; i++) {
// Make the comparaison case insensitive
if ((rows[i].deliveredToUser).toLowerCase() == `no`) {
userFound = true;
console.log(userFound);
var comport = rows[i].comport;
var command = "open" + rows[i].cubby_id;
var commandClose = "close" + rows[i].cubby_id;
var commandStatus = "status" + rows[i].cubby_id;
console.log(command);
console.log(comport);
var options = {
scriptPath: 'python/scripts',
// pass arguments to the script here
args: [command, comport, commandClose, commandStatus]
};
PythonShell.run('controlLock.py', options, function(err, results) {
if (err) {
res.render('errorConnection', {});
}
console.log('results: %j', results);
});
}
}
console.log(userFound);
// If the query fails to execute
} else {
console.log('Error while performing Query.');
res.render('errorConnection', {});
}
});
connection.end();
if (!userFound) {
//
res.render('pickup/errorAlreadyDelivered', {});
connection.end();
}
I would want this part at the end to be run only once the query has finished:
if (!userFound) {
//
res.render('pickup/errorAlreadyDelivered', {});
connection.end();
}
console.log("connection ended " + userFound);
I placed a console.log outside of the query and at the bottom and despite the query value changing to true it prints out false first, and comes out first because the console.log didn't wait until the query has finish to be able to store the value.

TypeError: Cannot read property 'toString' of undefined - why?

Here is the line (50) where this is happening:
var meetingId = meeting._id.toString(),
And here is the full, relevant code:
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var config = require('./config'),
xlsx = require('./xlsx'),
utils = require('./utils'),
_ = require('lodash'),
url = config.DB_URL;
var meetings = [];
function findNumberOfNotesByMeeting(db, meeting, callback) {
var meetingId = meeting._id.toString(),
meetingName = meeting.name.displayValue,
attendees = meeting.attendees;
host = meeting.host;
var count = 1, pending = 0, accepted = 0;
console.log("==== Meeting: " + meetingName + '====');
_.each(attendees, function(item) {
console.log(count++ + ': ' + item.email + ' (' + item.invitationStatus + ')');
if (item.invitationStatus == 'pending') { pending++; }
else if (item.invitationStatus == 'accepted') { accepted++; }
});
console.log("*** " + attendees.length + ", " + pending + "," + accepted);
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, doc) {
var emails = [];
if (doc.emails) {
doc.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
db.collection('notes').find({ 'meetingId': meetingId }).count(function(err, count) {
if (count != 0) {
console.log(meetingName + ': ' + count + ',' + attendees.length + ' (' + email + ')');
meetings.push([ meetingName, count, email, attendees.length, pending, accepted ]);
}
callback();
});
}
});
}
function findMeetings(db, meeting, callback) {
var meetingId = meeting._id.toString(),
host = meeting.host;
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, doc) {
var emails = [];
if (!err && doc && doc.emails) {
doc.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
db.collection('notes').find({ 'meetingId': meetingId }).count(function(err, count) {
if (count != 0) {
var cursor = db.collection('meetings').find({
'email': {'$regex': 'agu', '$options': 'i' }
});
}
callback();
});
}
cursor.count(function(err, count) {
console.log('count: ' + count);
var cnt = 0;
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
findNumberOfNotesByMeeting(db, doc, function() {
cnt++;
if (cnt >= count) { callback(); }
});
}
});
});
});
}
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findMeetings(db, function() {
var newMeetings = meetings.sort(function(m1, m2) { return m2[1] - m1[1]; });
newMeetings.splice(0, 0, [ 'Meeting Name', 'Number of Notes', 'Emails' ]);
xlsx.writeXLSX(newMeetings, config.xlsxFileNameMeetings);
db.close();
});
});
As you can see, the meeting variable (which I am almost 100% sure is the problem, not the _id property) is passed in just fine as a parameter to the earlier function findNumberOfNotesByMeeting. I have found some information here on SO about the fact that my new function may be asynchronous and needs a callback, but I've attempted to do this and am not sure how to get it to work, or even if this is the right fix for my code.
You're not passing the meeting object to findMeetings, which is expecting it as a second parameter. Instead of getting the meeting object, the function receives the callback function in its place, so trying to do meeting._id is undefined.
In fact, what is the purpose of the findMeetings function? It's name indicates it can either find all meetings in the database, or all meetings with a specific id. You're calling it without a meeting id indicating you might be trying to find all meetings, but its implementation takes a meeting object. You need to clear that up first.

Mysql select clause in Node.js

hello i wannna create sql caluse using this function
function selectFrom(reqContents, callback) {
connection.query('SELECT ?? FROM ?? WHERE ?', [ reqContents.attribute,
reqContents.table, reqContents.GET ], function(err, tuple, result) {
if (err) {
console.log(err);
} else {
callback(tuple);
}
});
}
First parameter(reqContents) is array and i have to use this function. But when i wrote multiple where conditions(below example), this query can't operate well.
Example :
reqContents.GET = {
id : user1,
passwd : 1
}
Here is a function I wrote to take the .GET params from reqContents and generate the where clause from its key, values
function buildQuery(params){
// Join the attributes to be in the form of att1,att2,att3
params.attribute = params.attribute.join(",");
// Generate WHERE clause conditions with AND between them
params.GET = (function generateWhere(keyValues){
var str = "";
for(var key in keyValues) {
str += key + " = " + (isNaN(keyValues[key])? '"'+keyValues[key]+'"': keyValues[key]);
if(Object.keys(keyValues).indexOf(key) != Object.keys(keyValues).length-1)
str+= " AND ";
};
return str;
})(params.GET);
return params;
}
This is what you need to do:
function selectFrom(reqContents, callback) {
reqContents = buildQuery(reqContents);
connection.query('SELECT ?? FROM ?? WHERE ?', [ reqContents.attribute,
reqContents.table, reqContents.GET ], function(err, tuple, result) {
if (err) {
console.log(err);
} else {
callback(tuple);
}
});

node.js async function in loop?

I am having some problems with node.js. What I'm trying to do is get an array of the directories in "./"+req.user.email and loop through them finding out their size and adding a table row to output, as you can see in the code. At the end I wan't to send all the table rows using res.send().
However the only output I am getting is:
<tr></tr>
for each file in the array. It seems that the forEach function is not waiting for readSizeRecursive at all. The readSizeRecursive function is asynchronous, and I believe that is what's causing the problem, but I don't know how I can fix this.
Any help would be greatly appreciated, I have included the readSizeRecursive function too. Thank you!
var output = "";
fs.readdir("./" + req.user.email, function (err, files) {
files.forEach(function(file){
output += "<tr>";
readSizeRecursive("./"+req.user.email+"/"+file, function (err, total){
output += '<td>' + file + '</td><td>' + total + '</td>';
});
output += "</tr>"
});
res.send(output)
});
readSizeRecursive() :
// Function to find the size of a directory
function readSizeRecursive(item, cb) {
fs.lstat(item, function(err, stats) {
var total = stats.size;
if (!err && stats.isDirectory()) {
fs.readdir(item, function(err, list) {
async.forEach(
list,
function(diritem, callback) {
readSizeRecursive(path.join(item, diritem), function(err, size) {
total += size;
callback(err);
});
},
function(err) {
cb(err, total);
}
);
});
}
else {
cb(err, total);
}
});
}
Please use the async module for this kind of pattern. Using async.each will allow you to compute the size for each folder asynchronously, and then return the sizes once you're done computing everything individually.
var output = [];
fs.readdir('./' + req.user.email, function (err, files) {
async.each(compute, report);
});
function compute (file, done) {
// calculate size, then callback to signal completion
// produce a result like below, then invoke done()
var obj = { files: [
{ name: file, size: size },
{ name: file, size: size },
{ name: file, size: size }
]};
output.push(obj);
done();
}
// doesn't need to be this awful
function format (list) {
var result = [];
list.forEach(function (item) {
var description = item.files.map(function (file) {
return util.format('<td>%s</td><td>%s</td>', file.name, file.size);
});
result.push(description);
});
result.unshift('<tr>');
result.push('</tr>');
return result.join('</tr><tr>');
}
function report (err) {
if (err) { return next(err); }
var result = format(output);
res.send(result);
}
This way you can easily swap out the different pieces of functionality, changing the formatting without altering the computing of the file size tree, for example.
Your main issue was control flow. You return with res.send while you are asynchronously looping and figuring out the sizes.
var fs = require ("fs");
var createTableContent = function (p, cb){
var read = function (p, cb){
//Prevent recursion if error
if (err) return cb ();
fs.stat (p, function (error, stats){
if (error){
err = error;
return cb ();
}
if (stats.isDirectory ()){
var dirSize = 0;
fs.readdir (p, function (error, entries){
if (error){
err = error;
return cb ();
}
var pending = entries.length;
//Empty dir
if (!pending) return cb (0);
entries.forEach (function (entry){
read (p + "/" + entry, function (entrySize){
dirSize += entrySize;
if (!--pending) return cb (dirSize);
});
});
});
}else{
cb (stats.size);
}
});
};
//A lot of errors can be produced, return only the first one
var err = null;
//Suppose p is a dir
fs.readdir (p, function (error, entries){
if (error) return cb (error);
var content = "";
var pending = entries.length;
if (!pending) return cb (null, content);
entries.forEach (function (entry){
read (p + "/" + entry, function (totalSize){
if (err) return cb (err);
content += "<tr><td>" + entry + "</td><td>" + totalSize + "</td></tr>";
if (!--pending){
//End
cb (null, content);
}
});
});
});
};
//Here goes the "email" path
createTableContent (".", function (error, content){
if (error) return console.error (error);
console.log (content);
});

Categories

Resources