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?

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); });
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).

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

1 Comment

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

Your Answer

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.