Reputation: 3620
I am trying to get my head around this non-blocking business.
Can you tell me what i am doing wrong here? I have tried to add a retrieveContactName function which gets more information from the db before writing to socket. I have tried to make it a callback but i get the error at bottom.
case 'getConversations':
var sip = parts[1];
var pass = parts[2].replace(/[\n\r]/g, ''); //strip that carriage return
var sql = "SELECT DISTINCT(session) FROM im WHERE sip = "+connection.escape(sip)+" AND password = "+connection.escape(pass)+" ORDER BY timestamp DESC";
connection.query(sql, function(err, results) {
if (err) winston.warn(err);
for (var i=0; i < results.length; i++) {
retrieveContactName(results[i].session, sip, pass, function(value) {
sock.write('Conversations '+results[i].session+' '+value+'\n');
});
}
});
break;
elsewhere
function retrieveContactName(session, user, pass, callback) {
var sql = "SELECT `im_from` FROM `im` WHERE `session` = "+connection.escape(session)+" AND `im_to` != "+connection.escape(session)+" AND `sip` = "+connection.escape(user)+" AND `password` = "+connection.escape(pass)+" LIMIT 1";
connection.query(sql, function(err, results) {
if (err) winston.warn(err);
if (results.length > 0 ) {
callback(results[0].im_from);
} else {
callback(session.replace("contact:",""));
}
});
}
and my error
TypeError: Cannot read property 'session' of undefined
at /home/ubuntu/socket/server.js:44:47
at Query._callback (/home/ubuntu/socket/server.js:79:4)
at Query.end (/home/ubuntu/socket/node_modules/mysql/lib/protocol/sequences/Sequence.js:75:24)
at Query._handleFinalResultPacket (/home/ubuntu/socket/node_modules/mysql/lib/protocol/sequences/Query.js:143:8)
at Query.EofPacket (/home/ubuntu/socket/node_modules/mysql/lib/protocol/sequences/Query.js:127:8)
at Protocol._parsePacket (/home/ubuntu/socket/node_modules/mysql/lib/protocol/Protocol.js:172:24)
at Parser.write (/home/ubuntu/socket/node_modules/mysql/lib/protocol/Parser.js:62:12)
at Protocol.write (/home/ubuntu/socket/node_modules/mysql/lib/protocol/Protocol.js:37:16)
at Socket.ondata (stream.js:38:26)
at Socket.emit (events.js:88:20)
Upvotes: 1
Views: 3816
Reputation: 36075
Your problem is down to not fully understanding scope, basically the issue is occurring here:
for (var i=0; i < results.length; i++) {
retrieveContactName(results[i].session, sip, pass, function(value) {
sock.write('Conversations '+results[i].session+' '+value+'\n');
});
}
The above will not work as you expect, all because by the time your callback fires i
will not have the value you expect... it will most likely be equal to results.length
which will give you an undefined
slot in results
. This is because the for
will most likely have continued on and finished it's execution before the callbacks ever occur. This is the principal of non-blocking, code does not wait, it carries on, and your callbacks have to be prepared for this.
In order to use the value of i
, or any variable that may change it's value outside the scope of your callback, you need to capture that value and store it with your callback. There are a few ways to do this but the nicest way is to pass the data your callback requires in as arguments — so you need to pass the results[i].session
(passed into retrieveContactName) on to your callback.
function retrieveContactName(session, user, pass, callback) {
var sql = "SELECT `im_from` FROM `im` WHERE `session` = "+connection.escape(session)+" AND `im_to` != "+connection.escape(session)+" AND `sip` = "+connection.escape(user)+" AND `password` = "+connection.escape(pass)+" LIMIT 1";
connection.query(sql, function(err, results) {
if (err) winston.warn(err);
if (results.length > 0 ) {
callback(results[0].im_from, session);
} else {
callback(session.replace("contact:",""), session);
}
});
}
And then:
for (var i=0; i < results.length; i++) {
retrieveContactName(results[i].session, sip, pass, function(value, session) {
sock.write('Conversations '+session+' '+value+'\n');
});
}
Obviously this is just a quick example, it may be best to pass in the actual result row — depending on what you want / need.
Upvotes: 2
Reputation: 83
results[i] may be out of scope inside the callback
case 'getConversations':
var sip = parts[1];
var pass = parts[2].replace(/[\n\r]/g, ''); //strip that carriage return
var sql = "SELECT DISTINCT(session) FROM im WHERE sip = "+connection.escape(sip)+" AND password = "+connection.escape(pass)+" ORDER BY timestamp DESC";
connection.query(sql, function(err, results) {
if (err) winston.warn(err);
for (var i=0; i < results.length; i++) {
retrieveContactName(results[i].session, sip, pass, function(value) {
sock.write('Conversations '+results[i].session+' '+value+'\n');
});
}
});
break;
can you place a console.log(results) just above:
sock.write('Conversations '+results[i].session+' '+value+'\n');
Upvotes: 0