Javascript 递归回调以创建家族树

Javascript 递归回调以创建家族树,javascript,recursion,keystonejs,Javascript,Recursion,Keystonejs,我正在尝试创建一个带有嵌套在回调函数中的回调函数的族谱,我希望得到至少5代。函数接收个人id,然后查找数据库中具有相同id的属性“父”的所有人 这是获取该人的子女的函数 var getChildren=function (person, callback) { keystone.list('Person').model.find().where('father', person.id).exec(function(err, children) { cal

我正在尝试创建一个带有嵌套在回调函数中的回调函数的族谱,我希望得到至少5代。函数接收个人id,然后查找数据库中具有相同id的属性“父”的所有人


这是获取该人的子女的函数

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);
            }
        })
    }
函数getFamilyTree(个人){
getChildren(个人、功能(儿童){
人.儿童=儿童;

对于(var i=0;i您肯定需要使用递归。我不知道您的数据看起来如何,或者
getChildren
如何工作,但这应该为您指明了正确的方向:

function getFamilyTree ( person ) {
    getChildren( person, function( children ) {
        person.children = children;
        for ( var i = 0; i < person.children.length ) {
             getFamilyTree( person.children[ i ] );
        }
    })
}
函数getFamilyTree(个人){
getChildren(个人、功能(儿童){
person.children=儿童;
对于(变量i=0;i
您肯定需要使用递归。我不知道您的数据是什么样子的,或者
getChildren
是如何工作的,但这应该为您指明了正确的方向:

function getFamilyTree ( person ) {
    getChildren( person, function( children ) {
        person.children = children;
        for ( var i = 0; i < person.children.length ) {
             getFamilyTree( person.children[ i ] );
        }
    })
}
函数getFamilyTree(个人){
getChildren(个人、功能(儿童){
person.children=儿童;
对于(变量i=0;i
如果使用而不是回调,则可以使用递归来解析任意深度的树:

函数getChildren(person){ 返回新承诺((解决、拒绝)=>{ keystone.list('Person').model.find().where('father',Person.id).exec((err,children)=>{ 如果(错误)拒绝(错误); (儿童); }); }); } 异步函数getFamilyTree(person,maxDepth,depth=0){ 如果(深度>=最大深度)返回人员; const children=(wait getChildren(person)).filter(isNotEmpty); person.children=等待承诺( map(child=>getFamilyTree(child,maxDepth,depth+1)) ); 返回人; } getFamilyTree({id:'rootPersonId'},5) .then(tree=>console.log(tree)) .catch(错误=>console.log(错误));
如果使用而不是回调,则可以使用递归来解析任意深度的树:

函数getChildren(person){ 返回新承诺((解决、拒绝)=>{ keystone.list('Person').model.find().where('father',Person.id).exec((err,children)=>{ 如果(错误)拒绝(错误); (儿童); }); }); } 异步函数getFamilyTree(person,maxDepth,depth=0){ 如果(深度>=最大深度)返回人员; const children=(wait getChildren(person)).filter(isNotEmpty); person.children=等待承诺( map(child=>getFamilyTree(child,maxDepth,depth+1)) ); 返回人; } getFamilyTree({id:'rootPersonId'},5) .then(tree=>console.log(tree)) .catch(错误=>console.log(错误));
简化代码的第一件事是拉出在
getFamilyTree
函数中多次使用的
外部
函数,这样就不会到处重复。为了简单起见,需要更新以将子节点作为参数而不是索引

由于您的回调每次都是相同的,因此您可以将其拉出到它自己的函数中。由于您在整个回调过程中不断引用
person
变量,因此需要对父项进行轻微更新

您的
外部
功能可以是:

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]);
    }
函数getChildrenCallback(子对象、父对象){ parent.children=children; 对于(变量i=0;i
}

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

由于您的回调每次都是相同的,因此您可以将其拉出到它自己的函数中。由于您在整个回调过程中不断引用
person
变量,因此需要对父项进行轻微更新

您的
外部
功能可以是:

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]);
    }
函数getChildrenCallback(子对象、父对象){ parent.children=children; 对于(变量i=0;i
}

非常感谢您的评论,因为前端是如何工作的,我需要检索此人的完整JSON家族树。此外,我尝试了您的代码,但它只检索了一代人,我不知道为什么我会在那里抛出一些
控制台。log
调用。我不认为这种逻辑是错误的,但很难知道w没有看到
getChildren
调用的结果或您正在查询的数据。因此,通过使用getChildren,它将以对象数组的形式检索个人的子对象,每个对象将包含关于每个子对象的信息。当个人没有任何子对象时,它将返回一个空白数组。非常感谢您的帮助注释,由于前端的工作方式,我需要检索此人的完整JSON族谱。此外,我尝试了您的代码,但它只检索了一代人,我不知道为什么我会在那里抛出一些
console.log
调用。我不认为这一逻辑是错误的,但如果没有看到res,很难知道
getChildren
调用的结果或您正在查询的数据。因此,通过使用getChildren,它将以对象数组的形式检索个人的子对象,每个对象将包含有关ea的信息