2017-05-06 45 views
1

我有一个简单的树,其中包含的id是Mongo集合的键。我正在使用名为treewalker的节点库。当我遍历树的每个节点时,我试图查找名称(使用猫鼬)并简单地将它附加到当前节点。如果我没有做回调来查找节点名称,只是使用一些固定值,我会得到我期待的值。让我来说明代码:在树形漫步完成后执行回调函数

这里是我的树:

{ 
    "categoryTree": [ 
    { 
     "categoryId": "1", 
     "children": [ 
     { 
      "categoryId": "2", 
      "children": [ 
      { 
       "categoryId": "3", 
       "children": [] 
      }, 
      { 
       "categoryId": "4", 
       "children": [] 
      } 
      ] 
     }, 
     { 
      "categoryId": "5", 
      "children": [] 
     }, 
     { 
      "categoryId": "6", 
      "children": [] 
     } 
     ] 
    }, 
    { 
     "categoryId": "7", 
     "children": [ 
     { 
      "categoryId": "8", 
      "children": [] 
     } 
     ] 
    } 
    ] 
} 

这里是代码,做什么,我想:只要我扔

catTree.categoryTree.forEach(function(node){ 
    var counter = 0; 
    tree.walkTree(node, 'children', function(obj){ 
     obj.name = counter++; 
    }); 
}); 
//This tree has the names (as the counter above) in it as I expect 
console.log(JSON.stringify(catTree)); 

然而,在猫鼬回调获取类别名称,打印的类别树不再具有名称。

catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     Cat.findById(obj.categoryId, {_id:0,name:1}).exec(function(err, value){ 
      obj.name = value.name; 
     }); 
    }); 
}); 
//This tree has NO names :(
console.log(JSON.stringify(catTree)); 

我知道这是一个时间问题,但我无法弄清楚如何解决它。我见过几个SO条款like this one,建议跟踪回调,并在所有被调用后继续。我无法弄清楚如何将这种模式应用到我的案例中,因为我正在行走一棵树,而不仅仅是迭代一个扁平列表。我开始认为我的问题可能是我正在使用树行程库,而不是在访问每个节点后用回调函数编写我自己的算法。

我真的很感谢你的帮忙!

+0

看看async.js – Alex

回答

2

您的数据库调用是异步的。这意味着他们将在未来完成一段时间,在迭代完成之后很久。如果你的数据库可以处理查询的一整棵树在它被扔在一次(运行基本并行所有这些查询),那么你可以做这样简单的东西:

let cntr = 0; 
catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     ++cntr; 
     Cat.findById(obj.categoryId, {_id:0,name:1}).exec(function(err, value){ 
      --cntr; 
      if (!err) { 
       obj.name = value.name; 
      } 
      // see if all requests are done 
      if (cntr === 0) { 
       console.log(JSON.stringify(catTree)); 
      } 
     }); 
    }); 
}); 

你想随时协调不止一个异步操作,通常使用承诺是有意义的(因为这正是它们的目的),并且猫鼬有内置的查询承诺。在这里,您将每个查询的承诺收集到一个数组中,然后Promise.all()告诉您何时完成。

let promises = []; 
catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     let p = Cat.findById(obj.categoryId, {_id:0,name:1}).exec().then(function(value) { 
      obj.name = value.name; 
     }); 
     promises.push(p); 
    }); 
}); 

Promise.all(promises).then(function() { 
    console.log(JSON.stringify(catTree)); 
}).catch(function(err) { 
    // error 
    console.log(err); 
}); 
+0

这太棒了!感谢答复和承诺解释。如果我可以给你买一瓶啤酒,我会的。 – tobyb

相关问题