[英]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.