Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript中的递归遍历树_Javascript_Node.js_Asynchronous - Fatal编程技术网

Javascript中的递归遍历树

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

在Java中,这是一项非常简单的任务,但javascript的异步特性使我几乎不可能完成这项任务,至少就我现在所知是这样。我喜欢这门语言

这是非常基本的。顶级树在mysql数据库中的父级为null。很容易找到孩子。孩子们可以用电话。树的深度是可变的

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