0

I have the following piece of javascript but for some scoping reason the "names" that is returned from myfunc is empty.

var myfunc = function(client, id) {
 var names = new Array();
 client.query(
 'SELECT stuff FROM mytable WHERE id="'+id+'"',
 (function selectCb(err, results, fields) {
 if (err) {
 throw err;
 }
 for (result in results) {
 // This prints fine
 console.log(results[result].name);
 names[result] = results[result].name;
 }
 client.end();
 })
 );
 // The following returns empty
 return names;
}
console.log(myfunc(1,2));

How can I make it break out of scope?

asked Nov 4, 2010 at 18:11

3 Answers 3

1

It's empty because the call to your "query" function is asynchronous. The function you pass into it won't be run until the results are available. Therefore, your "myfunc" function returns immediately, long before that callback function is invoked.

Using Javascript in a browser, you have to think in those terms. Instead of expecting your "names" to be ready immediately, change "myfunc" so that you pass it a callback function to be invoked when the names are actually available:

var myfunc = function(client, id, whenFinished) {
 var names = new Array();
 client.query(
 'SELECT stuff FROM mytable WHERE id="'+id+'"',
 (function selectCb(err, results, fields) {
 if (err) {
 throw err;
 }
 for (result in results) {
 // This prints fine
 console.log(results[result].name);
 names[result] = results[result].name;
 }
 client.end();
 if (whenFinished) whenFinished(names); // callback
 })
 );
};

Now when you call your function, instead of expecting the "names" as a return value, you'll pass in another function that will act on the list of names:

myfunc(1, 2, function(names) { console.log(names); });
answered Nov 4, 2010 at 18:17
Sign up to request clarification or add additional context in comments.

Comments

1

If client.query(...) is asynchronous, then the selectCb function would not have run and names would not have changed by the time myfunc returns. You need to redesign myfunc to return names asynchronously (by, for example, accepting a function parameter which it calls at the end of selectCb).

answered Nov 4, 2010 at 18:17

1 Comment

Could you give me a concrete example or point me to some reference? Thanks!
0
var names = new Array();
var myfunc = function(client, id) {
 client.query(
 'SELECT stuff FROM mytable WHERE id="'+id+'"',function selectCb(err, results, fields)
 {
 if (err) {
 throw err;
 }
 for (result in results) {
 // This prints fine
 console.log(results[result].name);
 names[result] = results[result].name;
 }
 client.end();
 }
 );
 // The following returns empty
 return names;
}
console.log(myfunc(1,2));

try making names global

answered Nov 4, 2010 at 18:17

1 Comment

That won't help, I don't think. Eventually the "names" array will be populated, but not immediately.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.