递归调用异步函数
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);
}
这是正在发生的事情,一步一步:
- 首先调用
foo()
。
- 然后调用
asyncBar(foo)
。
- 因为
asyncBar
是异步的,这意味着它启动了一个异步操作(假设它是一个http GET,但任何异步操作都可以)。该异步操作已启动,但随后 asyncBar()
立即 returns.
- 对
foo()
returns 的初始调用,堆栈已完全展开。堆栈上不再有 foo()
。
- 调用
foo()
之后的任何代码都会继续 运行 直到完成,然后 returns 返回事件循环。
- 同时异步操作在未来某个时间完成。这会在事件队列中调用您的回调。
- 当 JS 引擎执行完其他 Javascript(这意味着堆栈完全为空)时,它将事件从事件队列中拉出并调用回调。
- 在这种情况下,回调函数是
foo
因此它调用该函数并重新开始循环,回到第 2 步。
没有堆栈堆积。关键是异步回调会在当前堆栈完成、展开并返回系统后的某个时间调用。
在异步调用的情况下没有计算器溢出。
还,
您可以使用 async 模块的 during 方法 link,用于递归调用异步函数。
我有一个异步函数,我想连续多次调用它。 问题是"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);
}
这是正在发生的事情,一步一步:
- 首先调用
foo()
。 - 然后调用
asyncBar(foo)
。 - 因为
asyncBar
是异步的,这意味着它启动了一个异步操作(假设它是一个http GET,但任何异步操作都可以)。该异步操作已启动,但随后asyncBar()
立即 returns. - 对
foo()
returns 的初始调用,堆栈已完全展开。堆栈上不再有foo()
。 - 调用
foo()
之后的任何代码都会继续 运行 直到完成,然后 returns 返回事件循环。 - 同时异步操作在未来某个时间完成。这会在事件队列中调用您的回调。
- 当 JS 引擎执行完其他 Javascript(这意味着堆栈完全为空)时,它将事件从事件队列中拉出并调用回调。
- 在这种情况下,回调函数是
foo
因此它调用该函数并重新开始循环,回到第 2 步。
没有堆栈堆积。关键是异步回调会在当前堆栈完成、展开并返回系统后的某个时间调用。
在异步调用的情况下没有计算器溢出。
还,
您可以使用 async 模块的 during 方法 link,用于递归调用异步函数。