簡體   English   中英

遞歸回調創建家庭樹

[英]Recursive Callbacks to create a familly tree

我試圖用嵌套在回調函數中的回調函數創建一棵家譜,我希望至少有5代。 該函數接收該人的ID,然后該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);
            }
        })
    }

如您所見,它非常復雜。 它可以工作,但是有時它不能檢索全部5代,而只能檢索4或3代,有時甚至不能檢索1代,我也不知道為什么,請幫助我的家伙,我也是新來者,所以請對我輕松一點,提前致謝!

如果使用promise而不是回調,則可以使用遞歸async函數來解析任意深度的樹:

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

您肯定需要使用遞歸。 我不知道您的數據看起來如何,或者getChildren工作原理,但這應該為您指明正確的方向:

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

簡化代碼的第一件事是在整個getFamilyTree函數中getFamilyTree多次使用的outer函數,這樣就不會在整個地方重復該過程。 為了簡單起見,需要進行更新以將子節點作為參數而不是索引。

由於您的回調函數每次都是相同的,因此您可以將其提取到自己的函數中。 由於您在整個回調過程中不斷引用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]);
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM