Javascript中的递归遍历树
在Java中,这是一项非常简单的任务,但javascript的异步特性使我几乎不可能完成这项任务,至少就我现在所知是这样。我喜欢这门语言 这是非常基本的。顶级树在mysql数据库中的父级为null。很容易找到孩子。孩子们可以用电话。树的深度是可变的Javascript中的递归遍历树,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,在Java中,这是一项非常简单的任务,但javascript的异步特性使我几乎不可能完成这项任务,至少就我现在所知是这样。我喜欢这门语言 这是非常基本的。顶级树在mysql数据库中的父级为null。很容易找到孩子。孩子们可以用电话。树的深度是可变的 private static Set<Tree> getBranches( Tree trunk ) { Set<Tree> treeSet = new HashSet<Tree>();
private static Set<Tree> getBranches( Tree trunk ) {
Set<Tree> treeSet = new HashSet<Tree>();
if ( trunk != null ) {
if ( trunk.hasLines() ) { //queries if tree has lines. returns true or false
treeSet.add( trunk );
}
for ( Tree tree : trunk.treeList ) {
treeSet.addAll( getBranches( tree ) );
}
}
return treeSet;
}
我真的只需要输出这个根树中所有可用的子级
如果这不合理,请告诉我。我将尝试重构。我希望我能理解一些观点。我不想用纤维之类的东西来完成这件事,但我别无选择。谢谢。您必须使用异步
我已经修改了dig函数以使用async的forEach方法
function dig(tree_id, treeArray, AllDone) {
pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {
if (rows) {
async.forEach(
rows,
function(row, callback) {
hasLine(row.tree_id, function(t){
if (t) {
treeArray.push(row.tree_id);
callback();
}
else {
dig(row.tree_id, treeArray, callback);
}
});
},
function(err) {
if (err) AllDone(err, treeArray);
else AllDone(null, treeArray);
});
}
else
AllDone(null, treeArray)
});
}
treeArray = [];
dig(52, treeArray, function(err, t) {
res.json(t);
});
假设行是数组。。forEach遍历每一行并执行hasLine,每次迭代完成后都会调用回调函数,调用所有回调函数时都会调用AllDone。这里比较棘手的部分是递归,每个递归调用都有一个forEach循环,并且只有当所有回调都完成时,它才会调用AllDone方法
然而forEach是并行执行的,所以顺序是不受限制的
如果你不在乎秩序的话,我想这应该行得通
编辑:您可以使用forEachSeries解决订单问题。您当前使用的dig不一致:
// asynchronous with callback
dig(52, treeArray, function (t) {
res.json(t);
});
// then synchronous with `return`?
treeArray.concat(dig(rows[i].tree_id, treeArray));
另外,最后一行中的concat实际上并没有做很多工作,因为它不会改变调用它的数组。您可能并不希望它在树阵列周围进行挖掘,而不是像在GetBranchs中那样定义一个新的树集。因此,如果它这样做了,它每次都会将trearray附加到自身的末尾
您仍然可以将concat用于多个树集,但必须存储其返回值:
而且,您必须用异步迭代器替换for this循环,因为循环在继续之前不会等待异步操作。如果你想尝试的话,有一些选择
因此,对于多个树集、concat和,您可以尝试:
function dig(tree_id, callback) {
var treeSet = [];
hasLines(tree_id, function (yep) {
if (yep) {
treeSet.push(tree_id);
}
pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {
function each(row, next) {
dig(row.tree_id, function (subSet) {
treeSet = treeSet.concat(subSet);
next(null);
});
}
function done() {
callback(treeSet);
}
async.forEachSeries(rows, each, done);
});
});
}
dig(52, function (treeSet) {
res.json(treeSet);
});
那么,您的问题是如何在异步阅读树时保持输出中的原始树顺序呢;如果他真的关心秩序,那就完全是另一回事了。我想用forEach系列而不是像Jonathan的answerWow伙计们那样的forEach,这太棒了。在这一点上,我不确定该把哪一个标记为答案。谢谢你们的帮助。哇,伙计们,这太棒了。在这一点上,我不确定该把哪一个标记为答案。我倾向于这个答案,因为它更简单、简洁。谢谢
treeSet = treeSet.concat(subSet);
function dig(tree_id, callback) {
var treeSet = [];
hasLines(tree_id, function (yep) {
if (yep) {
treeSet.push(tree_id);
}
pool.query('SELECT * from tree where parent_id = ?', [tree_id], function (err, rows) {
function each(row, next) {
dig(row.tree_id, function (subSet) {
treeSet = treeSet.concat(subSet);
next(null);
});
}
function done() {
callback(treeSet);
}
async.forEachSeries(rows, each, done);
});
});
}
dig(52, function (treeSet) {
res.json(treeSet);
});