【问题标题】:achieve recursion in javascript在javascript中实现递归
【发布时间】:2013-11-05 13:59:57
【问题描述】:

我来自 c++ 背景,所以对回调机制不是很清楚。 与 java-script 混淆以实现递归。有人请帮忙。

这就是我想要达到的目标。

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: Maximum call stack size exceeded 错误。 javascript中如何实现递归?

编辑: 我正在写一个网络爬虫。 这就是我想要实现的。

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.

这只能通过递归来实现。我知道必须有终点/出口点。 一旦我解析了所有网络链接,我的退出点可能就在这里。它应该退出。

【问题讨论】:

  • 你的递归流程永远不会停止。
  • 我已经添加了。我需要实现超过一百万次的递归。
  • Javascript 不支持尾调用优化。一切都只是压入堆栈,但在达到最终情况之前不会弹出。在满足结束条件之前,您正在最大化堆栈大小。
  • @thgaskell 有什么办法可以克服吗?
  • 如果你需要运行一百万次,递归可能不是最好的方法。你想做什么?

标签: javascript node.js recursion


【解决方案1】:

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

【讨论】:

  • 确实,就像在 C++ 或任何其他语言中一样。
【解决方案2】:

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/

【讨论】:

【解决方案3】:
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>);

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

【讨论】:

    【解决方案4】:

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

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

    据我所知,某些浏览器不支持 SetImmediate。到目前为止,它仅在 IE10 中受支持。在服务器端,nodejs 支持这些 api。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-07
      • 2014-04-15
      • 2019-05-19
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多