我有一个分层系统。一个类别有一个parentid(如果它是一个根类别,则为0)。
类别DB中的示例行:
name | id | parentid
-----------+------+----------
Label | 71 | 8
我需要获得给定类别的所有子类别。所有人不仅指一个类别的直接孩子,而且指所有孩子的每个孩子。
我以前做过递归的东西,但是在同步环境中,并且它让我感到它不完全以同样的方式工作。
我知道我离工作解决方案并不遥远,但它并不适用于所有情况。注意:删除所有调试日志行不会混淆问题。
此外,欢迎任何简化和/或优化。例如,我不喜欢有两个回调,一个递归回调,最后一个...(但可能是由于异步它需要这样?)。
整个事情应该返回给定类别的所有子类别的ID的数组(allCats
)。
此当前解决方案适用于没有子级的单个类别,并且一级层次结构向下(并且allCats
正确包含所有ID)。它在两个级别失败(永远不会调用最终的回调,因此cnt
未正确更新?)。
通过致电Category.getAllSubCategories(categoryId);
Category.getSubCategories = function(cat, cnt, fullCats, cb, finalCb) {
Category.find({where: {parentId: cat.id}}, function(err, cats) {
if (err) {
cb(err);
}
if (cats.length > 0) {
var ids = [];
for (var i=0; i<cats.length; i++) {
ids.push(cats[i].id);
}
fullCats = fullCats.concat(ids);
cb(null, cnt, fullCats, cats, finalCb);
} else {
if (cnt > 0) cnt -= 1;
cb(null, cnt, fullCats, null, finalCb);
}
});
}
var catSearchCallback = function(err, cnt, fullCats, cats, finalCb) {
if (err) {
finalCb(err);
}
if (cats) {
for (var c=0; c<cats.length; c++) {
cnt += 1;
Category.getSubCategories(cats[c], cnt, fullCats, catSearchCallback, finalCb);
}
} else {
if (cnt == 0) {
finalCb(null, fullCats);
}
}
}
/* start here */
Category.getAllSubCategories = function(categoryId, cb) {
Category.findById(categoryId, function(err, cat) {
if (err) {
return logger.error(err);
}
var fullCats = []; //collection holding ALL ids
var cnt = 0; //counter to count how many steps we have done
if (cat) {
fullCats.push(categoryId); //the category in question needs to be in the results as well
Category.getSubCategories(cat, cnt, fullCats, catSearchCallback, function(err, allCats) {
if (err) {
cb(err);
}
cb(null, allCats);
});
} else {
return categoryId;
}
});
}
答案 0 :(得分:0)
以下SEEMS正在运行,我在我的系统中对零级,一级和两级层次结构进行了测试,并且它完成了预期的工作(到目前为止......)。
当然可能会有更优雅的解决方案,更有效的解决方案等。 如果你有的话,非常欢迎你分享。 对我来说,暂时,这有效:)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if touches.count <= 2 {
for touch: AnyObject in touches {
// do stuff
}
}
}
答案 1 :(得分:0)
我没有要使用的数据库,也没有完整的代码,例如我不知道Category.find
的工作方式。但是正如人们在评论中所说的那样,这是绝对可以使用Promise的代码,而当我们使用它时,为什么不使用async / await。我自己无法运行此代码,因此,请考虑它而不是完整的代码来作为蓝图/算法。所以,这里什么都没有。
用异步/等待方式重写代码:
Category.findAsync = function(condition){
return new Promise((resolve, reject) => Category.find(
condition,
(err, result) => err ? reject(err) : resolve(result)
))
}
Category.getSubCategories = async function(parentId){
return [parentId].concat(Promise.all(
(await Category.findAsync({where: {parentId}})).map(
subCategory => Category.getSubCategories(subCategory.id)
)
))
}
运行它:
(async()=>{
const categoryId = 12345
console.log(await Category.getSubCategories(categoryId))
})()
因为我不知道find
的工作原理,所以我在它周围写了一个名为findAsync
的包装,它将回调转换为promise。
*答案结尾*
PS:请所有等待/承诺专家编辑此答案并帮助OP达成可行的解决方案。