递归调用异步函数

Call asynchronous function recursively

我有一个异步函数,我想连续多次调用它。 问题是"multiple"可以是几十万,也可以是几百万...

显而易见的方法是像这样从回调中调用相同的函数:

function foo()
{
    asyncBar(foo);
}

当然涉及一些逻辑来停止递归。问题是堆栈是否充满了调用,并可能在某些时候导致堆栈溢出?

The question is whether the stack is filling with calls and may cause Whosebug at some point?

如果方法是异步的,那么你根本不会得到 Whosebug

检查下面的这个例子

function f1(n)
{
   if (n > 0 ) 
   {
       callAsynch(n, function(n){
          f1(n-1)
       });
   }
}

这个 callAsynch 可以是一个 Ajax 调用(或任何异步的调用),它将回调方法作为参数。

它不会堆积在堆栈上,因为每次调用都以调用异步方法结束,该方法不会将值返回给此方法,而只是将任务(调用 f1(n-1))附加到队列完成后。

The question is whether the stack is filling with calls and may cause Whosebug at some point?

否。 如果 asyncBar() 调用异步传递的回调,则不会建立堆栈。

在您的代码中:

function foo() {
    asyncBar(foo);
}

这是正在发生的事情,一步一步:

  1. 首先调用 foo()
  2. 然后调用 asyncBar(foo)
  3. 因为asyncBar是异步的,这意味着它启动了一个异步操作(假设它是一个http GET,但任何异步操作都可以)。该异步操作已启动,但随后 asyncBar() 立即 returns.
  4. foo() returns 的初始调用,堆栈已完全展开。堆栈上不再有 foo()
  5. 调用 foo() 之后的任何代码都会继续 运行 直到完成,然后 returns 返回事件循环。
  6. 同时异步操作在未来某个时间完成。这会在事件队列中调用您的回调。
  7. 当 JS 引擎执行完其他 Javascript(这意味着堆栈完全为空)时,它将事件从事件队列中拉出并调用回调。
  8. 在这种情况下,回调函数是 foo 因此它调用该函数并重新开始循环,回到第 2 步。

没有堆栈堆积。关键是异步回调会在当前堆栈完成、展开并返回系统后的某个时间调用。

在异步调用的情况下没有计算器溢出。
还, 您可以使用 async 模块的 during 方法 link,用于递归调用异步函数。