递归回调创建一个家庭树

时间:2018-05-18 16:16:19

标签: javascript recursion keystonejs

我正在尝试使用嵌套在回调函数中的回调函数创建一个家族树,我希望至少获得5代。该函数接收person的id,然后在数据库中查找具有相同id属性'father'的每个人。

这是获取此人的孩子的功能

var getChildren=function (person, callback) {
        keystone.list('Person').model.find().where('father', person.id).exec(function(err, children) {
            callback(children);
        })
    }

这就是我如何使用回调函数

function getFamilyTree(person){
        getChildren(person, function(children){
            person.children=children;
            for (var i=0;i<person.children.length;i++) {
                !function outer(i){
                    if (isNotEmpty(person.children[i])){
                        getChildren(person.children[i],function(children){
                                person.children[i].children=children;
                                for (var j=0;j<person.children[i].children.length;j++){
                                    !function outer(j){
                                        if (isNotEmpty(person.children[i].children[j])){
                                            getChildren(person.children[i].children[j],function(children){
                                                    person.children[i].children[j].children=children;
                                                    for (var k=0;k<person.children[i].children[j].children.length;k++){
                                                        !function outer(k){
                                                            if (isNotEmpty(person.children[i].children[j].children[k])){
                                                                getChildren(person.children[i].children[j].children[k],function(children){
                                                                    person.children[i].children[j].children[k].children=children;

                                                                })
                                                            }
                                                        }(k);
                                                    }
                                            })
                                        }

                                    }(j);
                                }
                        });
                    }

                }(i);
            }
        })
    }

你可以看到,它非常复杂。它有效,但有时它不会检索所有5代,但只有4或3,有时甚至1,我不知道为什么,请帮助我的家伙,我也是一个新来的人,所以请轻松与我,提前谢谢!

3 个答案:

答案 0 :(得分:2)

如果您使用promises而不是回调,则可以使用递归async function来解析任意深度的树:

function getChildren(person) {
  return new Promise((resolve, reject) => {
    keystone.list('Person').model.find().where('father', person.id).exec((err, children) => {
      if(err) reject(err);
      else resolve(children);
    });
  });
}

async function getFamilyTree(person, maxDepth, depth=0) {
  if(depth >= maxDepth) return person;
  const children = (await getChildren(person)).filter(isNotEmpty);
  person.children = await Promise.all(
    children.map(child => getFamilyTree(child, maxDepth, depth + 1))
  );
  return person;
}

getFamilyTree({id: 'rootPersonId'}, 5)
  .then(tree => console.log(tree))
  .catch(error => console.log(error));

答案 1 :(得分:0)

你肯定需要使用递归。我不确切知道您的数据的外观或getChildren的工作原理,但这应该指向正确的方向:

function getFamilyTree ( person ) {
    getChildren( person, function( children ) {
        person.children = children;
        for ( var i = 0; i < person.children.length ) {
             getFamilyTree( person.children[ i ] );
        }
    })
}

答案 2 :(得分:0)

为简化代码,您可以做的第一件事就是在outer函数中拉出多次使用的getFamilyTree函数,这样就不会在整个地方重复它。为简单起见,它需要更新以将子节点作为参数而不是索引。

由于你的回调每次都是一样的,你可以把它拉出来自己的功能。由于您在整个回调过程中不断引用person变量,因此需要稍微更新才能获取父项。

您的outer功能可能类似于:

function outer(child) {
    if (isNotEmpty(child)) {
        getChildren(child, getChildrenCallback);
    }
}

然后getChildrenCallback将是:

function getChildrenCallback(children, parent) {
    parent.children = children;
    for ( var i = 0; i < children.length; i++) {
        outer(child[i]);
    }

}