简体   繁体   English

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

[英]how to make this synchronous recursive function asynchronous

I have a javascript function that walks a tree recursively. 我有一个javascript函数,递归地遍历一棵树。 It has two "flag" variables that are set to false or true above the scope of the function itself, and so if a flag is set to true one time while the "walkTree" function is being recursed, it will be true for every recursion. 它有两个“标志”变量,在函数本身的范围之上设置为false或true,因此如果在递归“walkTree”函数时将标志设置为true,则每次递归都是如此。 On the other hand, the for loop might exist the function with a return as well if something is for. 另一方面,for循环可能存在带有返回的函数,如果有的话。 The problem I have is when there are too many recursions I get an error. 我遇到的问题是当递归太多时我会收到错误。

I'd like to prevent this problem by making this recursive function asynchronous, I've tried putting the sub walkTree() call inside the for loop into a setTimeout, but the problem I have now is that the rest of the function will be executed (and might return the wrong value) before the rest of the asynchronous stuff is done. 我想通过使这个递归函数异步来防止这个问题,我已经尝试将for循环中的子walkTree()调用放入setTimeout,但我现在遇到的问题是函数的其余部分将被执行(并且可能会返回错误的值),然后完成其余的异步操作。 So how can I make this asynchronous while still making sure the right value will be returned (and not the top function call in the recursion)? 那么我怎样才能使这个异步同时仍然确保返回正确的值(而不是递归中的顶级函数调用)?

As you can see the end of the function makes use of that flagB "variable" shared by all calls, and so we need to make sure all the recursive calls have been completed (and returned something) before the top one checks for these conditionals. 正如您所看到的,函数的结尾使用了所有调用共享的flagB“variable”,因此我们需要确保所有递归调用都已完成(并返回一些内容),然后才能检查这些条件。 Thanks! 谢谢!

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

}

Using timeouts to walk the tree, seriously? 使用超时来走树,认真吗? Have you considered to use iterative tree traversal instead of recursive? 您是否考虑过使用迭代树遍历而不是递归?

Example: 例:

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

Also see this so question and wikipeida article . 另见这个问题wikipeida文章

As alex vasi suggested, you might want to consider iterative tree traversal instead of recursive. 正如alex vasi所建议的那样,您可能需要考虑迭代树遍历而不是递归。 However, if your dataset is huge and processing the data takes a lot of time, your UI may freeze. 但是,如果您的数据集很大并且处理数据需要花费大量时间,那么您的UI可能会冻结。 Thus, you still might want to do the processing asynchronously. 因此,您仍可能希望异步进行处理。

Here's a modification of alex's example: 这是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();
}

The code snippet above does iterative traverse asynchronously, thus giving some time to the UI to update itself. 上面的代码片段以异步方式进行迭代遍历,从而为UI提供一些时间来更新自身。

Here's a jsFiddle where you can notice the difference between synchronous and asynchronous traverse. 这是一个jsFiddle ,您可以注意到同步和异步遍历之间的区别。 The synchronous traverse makes your browser to freeze for a small period of time, while the asynchronous version gives browser some time to breath while processing the tree. 同步遍历使您的浏览器冻结一小段时间,而异步版本在浏览器处理树时给浏览器一些时间。 (The code is a bit messy, sorry...) (代码有点乱,对不起......)

Edit: Updated jsFiddle 编辑:更新了jsFiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM