NodeJS and Express; callback on connection query completed - javascript

I am trying to insert several records in a mysql database and I need to get each record's ID and send it back to the client. The code I'm using:
app.post('/saveLesson',function(req, res){
var idArray = [];
let sections = JSON.parse(req.body.sections);
for (let i = 0; i < sections.length; i++) {
let sql = 'INSERT INTO sections (title, content, duration) VALUES ("' + sections[i].title + '","' + sections[i].content + '","' + sections[i].duration + '");';
connection.query(sql,
function (error, result) {
if (error) throw error;
idArray.push(result.insertId);
console.log('array in the loop: ' + idArray);
}
);
}
console.log('array out of the loop: ' + idArray);
res.send(idArray);
});
The problem is that the .query method seems to be asynchronous and the following code is executed before the idArray is actually populated:
console.log('array out of the loop: ' + idArray);
res.send(idArray);
What would be the appropriate way to deal with this issue?

Related

sql query inside loop failing [duplicate]

This question already has answers here:
What is the difference between "let" and "var"?
(39 answers)
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 1 year ago.
I have this:
var getDetailsForText = "select * from SCHEDULE where DATE BETWEEN '" + startDateRange + "' AND '" + endDateRange + "'"
console.log(getDetailsForText)
//figure out date = ''
ibmdb.open(ibmdbconn, function(err, conn) {
if(err)
return console.log(err);
conn.query(getDetailsForText, function(err, rows) {
if(err)
console.log(err);
let startDate = startDateRange.split(' ')
startDate = startDate[0]
let startTime = startDate[1]
let endTime = endDateRange.split(' ')
endTime = endTime[1]
for(var i = 0; i < rows.length; i++)
{
let clientPhoneNumber = ''
let clientName = ''
let trainerName = ''
console.log(rows[i])
var getUserWithEvent = "select * from users where username = '" + rows[i]["CLIENT_USERNAME"] + "'"
ibmdb.open(ibmdbconn, function(err, conn) {
if(err)
return console.log(err);
conn.query(getUserWithEvent, function(err, clientdata) {
if(err)
console.log(err);
console.log("test data!")
for(var i = 0; i < clientdata.length; i++)
{
console.log("test data!")
console.log(clientdata[i])
clientPhoneNumber = clientdata[i]["PHONE_NUMBER"]
clientName = clientdata[i]["FIRST_NAME"] + " " + clientdata[i]["LAST_NAME"]
}
/*
client.messages.create({
to: clientPhoneNumber,
from: 'mynum',
body: 'hello ' + clientName + ', your session begins in 24 hours. To cancel your session, reply CANCEL.'
}, function(err, data) {
if (err) {
console.log("err: " + err)
}
console.log(data)
});
*/
conn.close(function() {});
});
});
}
conn.close(function() {});
});
});
}, null, true)
What this does is it goes through the SCHEDULE table between the specific range. That part works and actually returns 2 results, which is right. But then, as you can see, I have a loop that loops through those results, which is fine, but then I do another SQL query which takes the CLIENT_USERNAME and queries the table with that. When i do that though, it returns 2 results, but both of them are the LAST result of the two. So it returns 2 results, but they are the identical results, which isn't right and shouldn't be happening. It then screws up my text messages. How can i fix this, what am I doing wrong? I can't figure it out!

node js redis loop through each hash key value

I am very new to redis & node and at the moment I am trying to loop through some test hash keys that i have created and print out to screen the results. Here is the result I expect to see:
{ "aaData": [['Tim Osbourne'],['Joe Bloggs'],['John Doe'],['Perry Coke'],['Will Holmes'],['Steven Smith']}
but instead I get this result:
{ "aaData": [[],[],[],[],[],[],]}'Tim Osbourne','Joe Bloggs','John Doe','Perry Coke','Will Holmes','Steven Smith',
Here is my code:
app = require('../app');
var redis = require("redis"),
client = redis.createClient();
routes = require('./');
var key_types = '';
client.keys("*", function (err, all_keys) {
key_types += '{ "aaData": [';
all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos
key_types += "[";
client.hmget([key, 'Owner of space'], function(err, field_val){
key_types = key_types + "'" + field_val + "',";
});
key_types += "],";
});
key_types += "]}";
});
app.get('/table_data', function(req, res){
res.render('table_data', { keys: key_types});
});
You should not do a keys *
It does not work because hmget is asynchronous, you should use the async module (async.map) for that.
What is the goal of [key, 'Owner of space'] since 'Owner of space' will always yield the same result?

Asynchrony in a database query

I have a problem when working with node.js. All have tried to describe in comments to the code.
The first thing I need to build an array of dialogs with some information about the interlocutors and the last meggase.
IM = {
iUserId: false,
socket: false,
checkDialog: function(socket) {
this.socket = socket;
// Returned [{owner: 123, viewer: 432}]
var sql = 'SELECT DISTINCT(`owner_user_id`), `viewer_user_id` FROM `phpfox_mail` WHERE `owner_user_id` = ' + this.iUserId + ' GROUP BY 1,2 UNION SELECT DISTINCT (`viewer_user_id`), `owner_user_id` FROM `phpfox_mail` WHERE `viewer_user_id` = ' + this.iUserId + ' GROUP BY 1,2 ORDER BY 1 ';
connection.query(sql, function(err, rows) {
if (err) throw err;
async.map(rows, function(item, nextParent) {
var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
var dialogs = [];
connection.query(sql, function(err, rows) {
// ???
});
}, function(err, item) {
// Here I have to get the generated array with all the necessary dialogue.
console.log(item);
IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
IM.socket.emit('dialogsBuilding', item);
});
});
}
};
Objective: To create an array of information about the message and interlocutors.
Scheme:
Get an array with all interlocutors. [{owner_user_id: 5757, viewer_user_id: 5866}, {etc...}]
Using the result of paragraph number 1, to get an array of information on the latest report from the dialogue. [{mail_id: 98, subject: test, owner: 5757, viewer: 5866, timestamp: 123566544}, {etc...}]
Get information about users for the specified identifier (owner_user_id/viewer_user_id).
Collect all the data on the dialogues in the same array.
I stopped at the third paragraph. Namely, I do not know how to consistently obtain information about users who are in the first two arrays.
Please, help my!
I don't believe you are using the async.map function correctly. Unfortunately you are using it so incorrectly that I cannot determine what it is you are actually trying to do. But here is an explanation of how you are misusing, vs the proper use of the async.map function.
Example from the async documentation:
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
Let's Simplify this a bit.
async.map(someArray, someFunction, someCallBack);
I believe your problem lies in the someFunction argument. Here is your version of this:
function(item, nextParent) {
var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
var dialogs = [];
connection.query(sql, function(err, rows) {
// ???
});
}
The function for this argument, if we consult the fs.Stat example, should take two arguments, this first is an item from the array we sent into async.map. This part I believe you have right. HOwever, the second argument is a callback, with two arguments. An error, and a set of results. This is the part I think you are messing up. You should call this callback. Internally async.map provides the callback argument, this callback argument is how async.map collects results into the array. Without the call to this, async.map cannot collect the results.
I believe what you want is this:
function(item, someCallBackArgument) {
var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
var dialogs = [];
connection.query(sql, function(err, rows) {
someCallBackArgument(err, rows);
});
}
I'm assuming this is a question about how to use async.map:
I've rewritten your code so it uses callbacks properly:
You will need to adjust the output but this should return you an array with all the data you require.
connection.query(sql, function(err, rows) {
if (err) throw err;
async.map(rows, function(item, callback) {
var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
var dialogs = [];
connection.query(sql, function(err, rows) {
if(err) return callback(err);
callback(null, { item: item, rows: rows} );
});
}, function(err, item) {
// Here I have to get the generated array with all the necessary dialogue.
console.log(JSON.stringify(item));
IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
IM.socket.emit('dialogsBuilding', item);
});
});
Yes! :)
IM = {
iUserId: false,
socket: false,
checkDialog: function(socket) {
this.socket = socket;
var sql = 'SELECT DISTINCT(`owner_user_id`), `viewer_user_id` FROM `phpfox_mail` WHERE `owner_user_id` = ' + this.iUserId + ' GROUP BY 1,2 UNION SELECT DISTINCT (`viewer_user_id`), `owner_user_id` FROM `phpfox_mail` WHERE `viewer_user_id` = ' + this.iUserId + ' GROUP BY 1,2 ORDER BY 1 ';
connection.query(sql, function(err, rows) {
if (err) throw err;
async.map(rows, function(item, nextParent) {
var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1;';
var dialogs = [];
connection.query(sql, function(err, rows) {
if(err) return nextParent(err);
nextParent(null, rows[0]);
});
}, function(err, item) {
async.map(item, function(dialog, next) {
connection.query('SELECT `user_name`, `full_name`, `user_profile_image` FROM `phpfox_user` WHERE `user_id` = ' + dialog.owner_user_id, function(err, user) {
next(err, {owner: user[0], dialog: dialog});
});
}, function(err, rows) {
async.map(rows, function(dialog, next) {
connection.query('SELECT `user_name`, `full_name`, `user_profile_image` FROM `phpfox_user` WHERE `user_id` = ' + dialog['dialog']['viewer_user_id'], function(err, user) {
next(err, {viewer: user[0], dialog: dialog['dialog'], owner: dialog['owner']});
});
}, function(err, dialogs) {
console.log(dialogs);
IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
IM.socket.emit('dialogsBuilding', dialogs);
});
});
});
});
}
And it worked! :)
Screen http://screencloud.net//img/screenshots/411f98a583916a41142c40294fd2ee00.png
But it seems to me, this code - it sucks!

can't get the results of select query in an array with javascript

I have a problem when trying to store the results of a select query into an array with java script .
the problem is that inside the function the array is containing the right values but outside it's empty , even when i used a global var it's still empty !!!
db.transaction(function (transaction) {
var sql = "SELECT * FROM Question where idEnq=" + idEn;
transaction.executeSql(sql, undefined, function (transaction, result) {
var res = document.getElementById('results');
res.innerHTML = "<ul>";
if (result.rows.length) {
for (var i = 0; i < result.rows.length; i++) {
var row = result.rows.item(i);
ch[i] = new qu(row.id, row.text, row.type);
res.innerHTML += '<li>' + row.id + ' ' + ch[i].text + ' ' + ch[i].type + '</li>';
}
tablo = ch;
} else {
alert("No choices");
res.innerHTML += "<li> No choices </li>";
}
res.innerHTML += "</ul>";
}, onError);
}); // here the ch and the tablo array are empty
You are using asynchronous functions. Anything that wants to use the data "returned" by those functions need to be in the callback. Of course you can assign this data e.g. to a global variable, but that variable will only have the value after the callback has run (asynchronously).
you're new so have look here http://pietschsoft.com/post/2008/02/JavaScript-Function-Tips-and-Tricks.aspx
there's a part talking about calling JavaScript Function asynchronously

Passing Javascript variable from one function to another function for use in a sqlite query

I am trying to write a Javascript function that obtains an array of unique ids from an sqlite database & then passes them to be used in another function where the ids can be used in another sql query, they also form part of a dynamically created list.
I have managed to pass the ids row['id'] to the array variable window.symp[i]. But I have not been able to access them correctly in the second function below, the second function correctly uses the ids to create the dynamic html but the variable passed to the sqlite query either fails or is the same value in all the list items created. Any help would be greatly appreciated - I have included both functions below:
function showContent() {
db.transaction(function (tx) {
tx.executeSql("SELECT id, notes FROM webkit WHERE notes LIKE 'A%'", [], function (tx, result) {
var notesanode = document.getElementById('notesa');
notesanode.innerHTML = "";
for (var i = 0; i < result.rows.length; ++i) {
var row = result.rows.item(i);
window.symp[i] = i;
window.symp[i] = row['id'];
var noteadiv = document.createElement('div');
noteadiv.innerHTML = '<li class=\"arrow\"><a id=\"0\" onClick=\"showSymptoms()\" href=\"#symptoms\">' + row['notes'] + " " + row['id'] + '</a></li>';
notesanode.appendChild(noteadiv);
}
}, function (tx, error) {
alert('Failed to retrieve notes from database - ' + error.message);
return;
});
});
}
function showSymptoms() {
db.transaction(function (tx) {
tx.executeSql("SELECT sid, symptom FROM slinks WHERE id LIKE ('" + symp + "')", [], function (tx, result) {
var symptomnode = document.getElementById('symptomid');
symptomnode.innerHTML = "";
for (var i = 0; i < result.rows.length; ++i) {
var row = result.rows.item(i);
var symptomdiv = document.createElement('div');
symptomdiv.innerHTML = '<p><label> <input type=checkbox>' + row['symptom'] + '</label></p>';
symptomnode.appendChild(symptomdiv);
}
}, function (tx, error) {
alert('Failed to retrieve notes from database - ' + error.message);
return;
});
});
}
I see two things:
The main issue is that you need
"SELECT sid, symptom FROM slinks WHERE id LIKE ('" + window.symp.join(',') + "')"
instead of what you have up there.
The second issue is that you have
window.symp[i] = i;
window.symp[i] = row['id'];
you can just go ahead and remove window.symp[i] = i; because it gets immediately overwritten by the line that follows it.

Categories

Resources