javascript - 在树遍历完成回调后执行函数

标签 javascript node.js mongoose callback tree

我有一个简单的树,其中的 ID 是 Mongo 集合的键。我正在使用一个名为 treewalker 的 Node 库.当我遍历树的每个 Node 时,我试图查找名称(使用 Mongoose )并将其简单地附加到当前 Node 。如果我不执行回调来查找 Node 名称,而只是使用一些固定值,我会得到我期望的值。让我用代码来说明:

这是我的树:

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

但是,一旦我抛出一个 mongoose 回调来获取类别名称,打印的类别树就不再有名称了。

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建议跟踪回调并仅在它们全部被调用后继续。我不知道如何将该模式应用到我的案例中,因为我正在走一棵树,而不仅仅是迭代一个平面列表。我开始认为我的问题可能是我正在使用 treewalker 库,而不是在访问每个 Node 后编写我自己的带有回调的算法。

非常感谢您的帮助!

最佳答案

您的数据库调用是异步的。这意味着它们在将来的某个时间完成,在 .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));
            }
        });
    });
});

任何时候当您试图协调多个异步操作时,使用 promises 通常是有意义的(因为这正是它们的构建目的),而 mongoose 内置了用于查询的 promises。在这里,您将每个查询的 promise 收集到一个数组中,然后 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);
});

关于javascript - 在树遍历完成回调后执行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43825821/

相关文章:

node.js - Mongoose 从没有模型的集合中删除

javascript - jquery - 在两个 .filter() 之后获取脚本标签的问题

javascript - Kinetic.js - 图像不显示

node.js - 使用 mongoose 从 NodeJS 后端连接 MongoDB 错误

javascript - 如何安全地接受包含来自所见即所得编辑器的 iframe 的用户输入?

node.js - 使用 Mongoose 在 MongoDB 中创建关系(在 Node.js 中)

javascript - 将类似的 JSON 对象分组到数组中

JavaScript/Firefox : "Failed to register/update ServiceWorker", 当没有使用名为 ServiceWorker 的内容时

node.js - Mongoose 填充不填充

node.js - 如何加快 mongoose 批量文档更新速度