2011-11-14 108 views
6

我有一个递归地走树的javascript函数。它有两个“标志”变量,在函数本身的范围之上被设置为false或true,所以如果一个标志在“walkTree”函数被递归时被设置为true,那么对于每个递归。另一方面,for循环可能存在带返回值的函数,如果有的话。我遇到的问题是当递归过多时出现错误。如何使这个同步递归函数异步

我想通过使这个递归函数异步来防止这个问题,我已经尝试将for循环中的子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; 
    } 

} 
+0

异步功能将无法返回一个有用的值,你需要提供一个回调函数作为参数。 – zzzzBov

+0

为什么你没有检查元素(参数)是否有循环前通过他们的孩子? – Headshota

+0

叶在我的实际功能,我正在做如果(n.children!= undefined && n.children.length> 0) –

回答

1

正如alex 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(); 
} 

代码段上面并迭代遍历异步,从而使一些时间到UI更新自身。

这里有一个jsFiddle,您可以看到同步和异步遍历之间的区别。同步遍历使得浏览器在一段时间内冻结,而异步版本为浏览器在处理树时留出一些时间来呼吸。 (代码是有点乱,对不起...)

编辑:更新的jsfiddle

+0

啊!非常好,谢谢!我会尝试使这个异步,并看看它是否有助于有时的用户界面。谢谢! –

1

使用超时走树,认真吗?你有没有考虑过使用迭代树遍历而不是递归?

实施例:

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

另见this so questionwikipeida article

+0

谢谢,将来看看这个。我一直试图让这个递归函数工作,我还没有想过寻找另一种方式。 –

+0

请注意,如果您的树很大,您可能仍然希望使用异步解决方案来防止UI冻结。 – rap1ds