This question already has answers here:
Is this type of recursion bad in JavaScript? If so, how should I rewrite it? [closed]
(2个答案)
已关闭6年。
作为一个简单的示例程序,我有一个 Node 脚本,该脚本连续ping服务器,并希望该程序能长时间运行。
该程序被设置为可返回Promise对象的ping函数。根据ping是成功还是失败,来兑现或拒绝 promise 。
我希望此功能循环运行,因此无论ping是否成功,在之后的一定时间之后,将先解决上一个请求,然后再触发下一个ping。
问题不在于此任务本身,而是我对自己的实现感到担忧。我相信它将最终导致堆栈溢出。
这是一些代码,以查看发生了什么:
我试图限制代码只是为了反射(reflect)以下问题的范围:
这最终会导致堆栈溢出吗?
有没有一种模式可以在使用promise时防止基于回调的循环溢出? 安排第一次ping时: 运行第一次ping时: 收到第一个响应时: 当第二个超时时间到期时:
如您所见,每次您等待 promise 或超时时,控件都会返回到事件循环。当事件(例如达到超时或收到ping响应)时,事件循环将调用为该事件注册的回调。
(2个答案)
已关闭6年。
作为一个简单的示例程序,我有一个 Node 脚本,该脚本连续ping服务器,并希望该程序能长时间运行。
该程序被设置为可返回Promise对象的ping函数。根据ping是成功还是失败,来兑现或拒绝 promise 。
我希望此功能循环运行,因此无论ping是否成功,在之后的一定时间之后,将先解决上一个请求,然后再触发下一个ping。
问题不在于此任务本身,而是我对自己的实现感到担忧。我相信它将最终导致堆栈溢出。
这是一些代码,以查看发生了什么:
function doPing(host) {
// returns a promise object.
}
function doEvery(ms, callback, callbackArgs) {
setTimeout(function() {
callback.apply(null, callbackArgs)
.always(function() {
doEvery(ms, callback, callbackArgs);
});
}, ms);
}
doEvery(1000, doPing, [host]);
我试图限制代码只是为了反射(reflect)以下问题的范围:
这最终会导致堆栈溢出吗?
有没有一种模式可以在使用promise时防止基于回调的循环溢出?
最佳答案
这里没有堆栈溢出。 setTimeout
是一个异步函数:它调度要运行的函数,但不会立即调用它。由于重复调用doEvery
在setTimeout
的回调内,因此将确保它不会溢出。
这是最深的堆栈在各个点上可能看起来像的示例:
[global scope] -> doEvery -> setTimeout
[event loop] -> [handle timer] -> [closure #1 in doEvery] -> callback.apply -> doPing
[event loop] -> [handle network] -> promise.resolve -> [closure #2 in doEvery] -> doEvery -> setTimeout
[event loop] -> [handle timer] -> [closure #1 in doEvery] -> callback.apply -> doPing
如您所见,每次您等待 promise 或超时时,控件都会返回到事件循环。当事件(例如达到超时或收到ping响应)时,事件循环将调用为该事件注册的回调。
关于javascript - 避免在基于promise的循环中递归堆栈溢出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30054859/
10-16 20:58