Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我应该如何处理许多嵌套匿名函数中的作用域?_Javascript_Node.js_Mongodb - Fatal编程技术网

Javascript 我应该如何处理许多嵌套匿名函数中的作用域?

Javascript 我应该如何处理许多嵌套匿名函数中的作用域?,javascript,node.js,mongodb,Javascript,Node.js,Mongodb,我在mongodb中有一个集合,其中包含嵌入的引用文档,这迫使我运行多个anon函数 首先我初始化这个数组 var player = { name : '', life : 10, gold : 50, score : 0, clientId : socket.id, playerId : data.playerId, deck : [] }; 现在我需要通过从mongodb获取数据来向数据组添加数据 // First find

我在mongodb中有一个集合,其中包含嵌入的引用文档,这迫使我运行多个anon函数

首先我初始化这个数组

  var player = {
    name : '',
    life : 10,
    gold : 50,
    score : 0,
    clientId : socket.id,
    playerId : data.playerId,
    deck : []
  };
现在我需要通过从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());
  });
});
现在的问题是,播放器数组仍然保持最初初始化时的状态。为什么我在player中的数据不存在?我知道为什么,因为它不在匿名函数中调用时在另一个作用域中。但是我应该如何将我的值添加到播放器数组中呢

这些片段是完整的

// 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);

虽然Node.JS是单线程的,但它基于事件。完成工作并等待其他工作完成。等待MongoDB调用返回就是一个可以等待的完美例子。在本例中,这意味着当节点进程等待响应时,它可以执行其他JavaScript代码。最后,MongoDB做出响应,并在下一次等待其他工作机会时执行代码

下面标记为1,代码在playerCol.find返回之前执行。Node.JS和MongoDB驱动程序是异步的。这意味着调用find的结果直到初始调用完成后才会返回。稍后,当数据库用这些值响应时,将进行回调。在对playerCol.find的第一次调用中,回调函数是在toArray中声明的内部函数。我已将其重命名为findPlayerAsync

因此,在执行查找之后,下一行就是console.logplayer.deck。如果在find:之后添加一个标记字符串,您将看到该值在另一个console.log执行标记为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);
我希望控制台是:

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

闭包和数据看起来没问题,我看不出您在嵌套范围内重新声明player变量。您在哪里检查播放器数组的值?它需要在towerCall调用完成之后。toArray在push调用之后完成。但是deck是,如果在push之后执行console.logplayer,则值确实存在。@martin yes在我看到您的comment@WiredPrairie如果我在推送之后将player对象记录为console.log,则该值存在。但是,如果我将console.log移出playerCol.find函数,数据就会消失。如果这不起作用,您需要发布更多的代码:值的console.log唯一起作用的地方是tower.find调用的末尾。因为它都是异步的,这就是为什么会有回调,所以您需要等到所有的工作都完成了。如果您只是在playerCol.find函数之后记录值,它将始终为空,因为其他代码还没有返回。谢谢WiredPairie,这是非常详细的解释。虽然这很有道理,但我仍在为我应该如何处理它而挣扎。我可以强制它以任何方式等待数据库请求吗?或者有没有一种方法可以不使用异步回调来执行mongodb查询?您可能希望查看类似于for node的库。