How should i handle scope within many nested anonymous functions?

I have a Collection in mongodb, which contains embedded referenced documents, which forces me to run thought multiple anon functions.

First i initialize this array

  var player = {
    name : '',
    life : 10,
    gold : 50,
    score : 0,
    clientId : socket.id,
    playerId : data.playerId,
    deck : []
  };

Now i need to add data to the deck, by fetching data from mongodb.

// First find the player. 
  var playerCol = db.collection('Guest');
  playerCol.find({'_id' : new ObjectId(data.playerId)}).toArray(function(err, playerRes) {
    // Traverse and load each tower in deck.
// Traverse each embedded reference, so each can be fetched.
playerRes[0].deck.towers.forEach(function(tower) {
  // fetch data for tower.
  towerCol = db.collection('Tower');
  towerCol.find({'_id' : new ObjectId(tower.oid)}).toArray(function(err, completeTower) {
    // Add the tower data to the deck.
    player.deck.push(completeTower.pop());
  });
});

Now the problem is that the player array is still as it was, when it was first initialized. Why doesn't my data in player persist? Well i know why, because it's in another scope when not called inside a anonymous function. But how should i approach adding my values to the player array?

The snippets in one piece.

// Initialize the player.
var player = {
  name : '',
  life : 10,
  gold : 50,
  score : 0,
  clientId : socket.id,
  playerId : data.playerId,
  deck : []
};

// Load players deck.
var playerCol = db.collection('Guest');
playerCol.find({'_id' : new ObjectId(data.playerId)}).toArray(function(err, playerRes) {
// Traverse and load each tower in deck.

playerRes[0].deck.towers.forEach(function(tower) {

  towerCol = db.collection('Tower');
  towerCol.find({'_id' : new ObjectId(tower.oid)}).toArray(function(err, completeTower) {
    player.name = "Melvar";
    player.deck.push(completeTower.pop());
    console.log(player.deck); // Prints the data, just pushed
  });
});

console.log(player.deck); // Prints empty array.
process.exit(1);

While Node.JS is single threaded, it's based on events. Do work and wait for other work to complete. Waiting for a MongoDB call to return is a perfect example of something that can be "waited" upon. In this case, it means that while the Node process is waiting for a response, it can execute other JavaScript code. Eventually, MongoDB responds, and the code is executed at the next "wait for other work" opportunity.

Marked as #1 below, the code executes before the playerCol.find returns. Node.JS and the MongoDB drivers are asynchronous. This means that the results of calling find aren't returned until after the initial call is made. Later, when the database has responded with the values, the callback is made. In the first call to playerCol.find, the callback is the inner function declared with in toArray. I've renamed it to findPlayerAsync.

So, right after the find is executed, the next line that runs is the console.log(player.deck). If you add a marker string as shown after find:, you'll see that value is displayed on the console before the other console.log executes (marked as #2).

// Load players deck.
var playerCol = db.collection('Guest');
playerCol.find({'_id' : new ObjectId(data.playerId)}).toArray(function findPlayerAsync(err, playerRes) {
// Traverse and load each tower in deck.

playerRes[0].deck.towers.forEach(function(tower) {

  towerCol = db.collection('Tower');
  towerCol.find({'_id' : new ObjectId(tower.oid)}).toArray(function findTowerAsync(err, completeTower) {
    player.name = "Melvar";
    player.deck.push(completeTower.pop());
    console.log('Inside towerCol.find: ' + player.deck); // #2 Prints the data, just pushed
  });
});

console.log('After find: ' + player.deck); // #1 Prints empty array.
process.exit(1);

I'd expect the console to be:

After find: []
Inside towerCol.find: [......]