Javascript 如何使这个同步递归函数异步

Javascript 如何使这个同步递归函数异步,javascript,asynchronous,recursion,Javascript,Asynchronous,Recursion,我有一个递归遍历树的javascript函数。它有两个“flag”变量,在函数本身的作用域上方设置为false或true,因此,如果在递归“walkTree”函数时将一个标志设置为true,则每次递归都为true。另一方面,如果某个函数是for,则for循环也可能存在带有返回的函数。我的问题是当有太多的递归时,我会得到一个错误 我想通过使这个递归函数异步来防止这个问题,我曾尝试将for循环中的sub walkTree()调用放入setTimeout,但现在的问题是,在完成其他异步操作之前,将执行

我有一个递归遍历树的javascript函数。它有两个“flag”变量,在函数本身的作用域上方设置为false或true,因此,如果在递归“walkTree”函数时将一个标志设置为true,则每次递归都为true。另一方面,如果某个函数是for,则for循环也可能存在带有返回的函数。我的问题是当有太多的递归时,我会得到一个错误

我想通过使这个递归函数异步来防止这个问题,我曾尝试将for循环中的sub walkTree()调用放入setTimeout,但现在的问题是,在完成其他异步操作之前,将执行函数的其余部分(可能返回错误的值)。那么,在确保返回正确的值(而不是递归中的顶级函数调用)的同时,如何使此异步化呢

正如您所看到的,函数的结尾使用了所有调用共享的flagB“变量”,因此我们需要确保所有递归调用都已完成(并返回了一些内容),然后顶部的函数才会检查这些条件。谢谢

var flagA = false;
var flagB = false;

var walkTree = function (n) {
  var sub;

  for (var i = 0; i < n.children.length; i++) {
      sub = walkTree(n.children[i]);
      if (sub === 'something-special') {
        return sub;
      }
  }

  var test = doSomethingWith(n);

  if (test === "something") {
    flagA = true;
  }

  if (test === "something-else") { 
    flagB = true;
  }

  if (flagB === true) {
    return true;
  }
  if (test === "something-special") {
    return test;
  } else {
    return false;
  }

}
var flagA=false;
var flagB=假;
var walkTree=函数(n){
var-sub;
for(var i=0;i
真的要用超时在树上行走吗?您是否考虑过使用迭代树遍历而不是递归树遍历

例如:

var walkTree = function(node) {
    var queue = [node];
    while (queue.length) {
        var n = queue.shift();
        for (var i = 0; i < n.children.length; i++) {
            queue.push(n.children[i]);
        }
        doSomethingWith(n);
    }
}
var walkTree=函数(节点){
变量队列=[node];
while(queue.length){
var n=queue.shift();
for(var i=0;i

也见.

< P>亚历克斯Vasi建议,您可能需要考虑迭代树遍历而不是递归。但是,如果您的数据集很大,并且处理数据需要很多时间,那么您的UI可能会冻结。因此,您可能仍然希望异步进行处理

下面是对alex示例的修改:

function asyncIterativeWalkTree(node) {
    var queue = [node];

    var processQueue = function() {
        var n = queue.shift();
        for (var i = 0; i < n.children.length; i++) {
            queue.push(n.children[i]);
            setTimeout(processQueue, 0);
        }
        doSomethingWith(n);
    }

    processQueue();
}
函数asyncIterativeWalkTree(节点){
变量队列=[node];
var processQueue=函数(){
var n=queue.shift();
for(var i=0;i
上面的代码片段以异步方式进行迭代遍历,从而给UI一些时间进行自我更新

在这里,您可以注意到同步遍历和异步遍历之间的区别。同步遍历使浏览器冻结一小段时间,而异步遍历使浏览器在处理树时有一些喘息的时间。 (代码有点乱,对不起…)


编辑:更新的JSFIDLE

异步函数无法返回有用的值,您需要提供回调函数作为参数。为什么不在循环元素(参数)之前检查元素(参数)是否有子元素?是的,在我的实际函数中,如果(n.children!=未定义和&n.children.length>0)我仍然不太清楚回调函数作为参数是如何递归的。我也不知道怎么做。谢谢,我不知道你的函数应该做什么,也不知道你是否有意在函数之外使用变量。函数从不返回
“特殊的东西”
,但您正在检查
if
语句中的返回值。谢谢,我们将对此进行研究。我一直在尝试使这个递归函数工作,但我没有想到要寻找另一种方法。请注意,如果您的树很大,您可能仍然希望使用异步解决方案来防止UI冻结。啊!非常好,谢谢!我将尝试使其异步化,并查看它有时是否有助于UI。谢谢