我正在尝试使用嵌套在回调函数中的回调函数创建一个家族树,我希望至少获得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,我不知道为什么,请帮助我的家伙,我也是一个新来的人,所以请轻松与我,提前谢谢!
答案 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]);
}
}