使用callback完成树行走后执行一个函数

我有一个简单的树,id是Mongo集合的关键。 我正在使用一个名为treewalker的节点库。 当我走树的每个节点时,我试图查找名称(使用mongoose),并简单地将其附加到当前节点。 如果我不做callback查找节点名称,只是使用一些固定值,我得到我期待的价值。 让我用代码来说明:

这是我的树:

{ "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)); 

但是,只要我扔了一个mongoosecallback获得类别名称,打印的类别树不再有名称。

 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文章,这些文章build议跟踪callback,并在所有被调用之后继续。 我无法弄清楚如何将这个模式应用到我的案例中,因为我正在走一棵树,而不是迭代一个扁平列表。 我开始认为我的问题可能是我正在使用树行程库,而不是在访问每个节点后用callback编写我自己的algorithm。

我真的很感谢你的帮助!

你的数据库调用是asynchronous的。 这意味着在.forEach()迭代结束之后很长一段时间。 如果你的数据库可以同时处理整个查询树(基本上并行地运行所有这些查询),那么你可以做一些简单的事情:

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

任何时候,当你试图协调多个asynchronous操作时,通常使用promise(因为这正是它们的目的),mongoose有内置的查询。 在这里,你从每个查询收集一个承诺到一个数组,然后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); });