0

Why is the new Monsters object only being filled while being called inside the mysql function scope?

    Monsters = {};
db.query('SELECT * from rpg_monsters ', function(err, results) {
        for(i=0; i < results.length; i++){
        Monsters[results[i].monster_id] = {
                monster_id: results[i].monster_id,
                monster_name: results[i].monster_name,
                monster_filename: results[i].monster_filename,
                monster_hp: results[i].monster_hp,
                monster_chp: results[i].monster_hp,
                monster_type: results[i].monster_type,
                monster_level: results[i].monster_level,
                xPosition: results[i].monster_xPosition,
                yPosition: results[i].monster_yPosition
            }
        }
 console.log(Monsters); // This Returns True with all the objects properties!
db.end();
});
console.log(Monsters); // This Returns Empty?

Is it possible use the Monsters object (or any) outside of the mysql callback?

NiCk Newman
  • 1,716
  • 7
  • 23
  • 48
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Rodrigo Medeiros Mar 10 '15 at 03:25

1 Answers1

1

Short answer: No.

Long answer: Welcome to asynchronous programming in NodeJS! Your error is not due to a scoping issue, but a time issue! Your asynchronous code does not run in source order. Your code does this:

  1. initialize global variable Monsters reference an empty Javascript object
  2. submit an asynchronous request to db.query, and pass a callback taking params err and results
  3. console.log the contents of Monsters, which still references an empty array

NodeJS reaches the end of it's main loop and ticks. This may happen many times while waiting for db.query to finish its asynchronous IO. At some point in the future we resume:

  1. db.query resolves and runs your callback function.
  2. clone all elements in results into object at global variable Monsters
  3. log value of Monsters

You will need to restructure your code to follow the asynchronous callback structure, or you can invesetigate alternatives like Promises or coroutines.

Please see How to return the response from an asynchronous call?, it has quite the explanation of your issue.

Community
  • 1
  • 1
Just Jake
  • 4,698
  • 4
  • 28
  • 33
  • Boom. Just added a function callback and assigned my Monsters object to 'this.data', and passed this.data as a parameter to another function. Everything works outside of that now. Thank you for the explanation as well, marked. I love this site :) – NiCk Newman Mar 10 '15 at 04:00