在javascript中实现递归

时间:2013-11-04 10:57:14

标签: javascript node.js recursion

我来自c ++背景,因此对回调机制不太清楚。 与java脚本混淆以实现递归。有人请帮忙。

这就是我想要实现的目标。

Method 1(on success - call Method2);
Method 2(on success - call Method3);
Method 3(on success - call Method1)

这是我的代码。

function Method1(val1, val2, callback) {
   console.log('Method1' + val1);
   callback(val1, Method3);
}

function Method2(val1, fn) {
  console.log('Method2 ' + val1);
  val1++;
  fn(val1);
}

function Method3(val){
    console.log('Method3 ' + val);
    val++;
    if(val > 1000)  process.exit(0);
    else {
        Method1(val,2, Method2);
    }
}

Method1(1,2,Method2);

一旦我运行它会抛出 RangeError:超出最大调用堆栈大小错误。 如何在javascript中实现递归?

编辑: 我正在写一个webcrawler。 这就是我想要实现的目标。

1. Get the URL to be crawled.
2. Store the content(webpage) in a file. 
3. Parse the content. Get all the links in the file. 
4. call step 2 for each link in the content.

这只能通过递归来实现。我明白必须有终点/退出点。 在这里,我的退出点可能是我解析所有的网络链接。它应该退出。

4 个答案:

答案 0 :(得分:2)

你需要说什么时候停止,否则它会继续调用每个方法,导致你的错误。

答案 1 :(得分:1)

Javascript不支持尾调用优化。所有东西都被推到堆栈上,但是在到达最终案例之前不会弹出。

在达到最终条件之前,您最大化了堆栈大小。

  

有什么方法可以克服这个问题吗?

有各种方法,但我认为最简单的方法是设置使用setTimeout以便稍后使用其参数调用函数。


例如:

function count(n, end) {
    console.log(n);
    if (n < end) {
        count(n+1, end);
    }
}
count(0, 100000) // More than enough to exceed the stack limit

这将尝试打印0到100000之间的所有数字,但它在到达结尾之前达到最大堆栈大小。


因此,不是直接调用它,而是可以通过将其传递到setTimeout函数来推迟执行时间,该函数将获取函数及其参数并在以后运行它。使用setTimeout的另一个好处是调用将是异步的,这意味着其他代码可以同时运行。

function count(n, end) {
    console.log(from);
    if (n < end) {
        setTimeout(count, 0, n+1, end);
    }
}
count(0, 100000) // More than enough to exceed the stack limit, but it will run!

有关计划如何运作的更多信息:http://ejohn.org/blog/how-javascript-timers-work/

答案 2 :(得分:0)

function Method1(<params>){
   // condition
   if(<params>){
      Method2(<params>);
   }else{
      return;
   }

}

function Method2(<params>){
   // condition
    if(<params>){
      Method3(<params>);
   }else{
      return;
   }
}

function Method3(<params>){
   // condition
    if(<params>){
      Method1(<params>);
   }else{
      return;
   }
}

Method1(<params>);

注意:它需要一些条件来打破递归循环,否则它不会结束循环。

答案 3 :(得分:0)

可以通过setImmediate或setTimeout或process.nextTick(nodejs)函数来实现。有效的方法是setImmediate。以下链接中给出的原因。

Setimmdiate API:http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg
SetImmediate与nextTick(SO):setImmediate vs. nextTick
解释1:http://www.nczonline.net/blog/2013/07/09/the-case-for-setimmediate/
解释2:http://howtonode.org/understanding-process-next-tick

根据我的知识,某些浏览器不支持SetImmediate。它仅在IE10中受支持。在服务器端,nodejs支持那些api。