As a simple example program, I have a node script which pings a server continuously, and wish for this program to be ran for a long time.
The program is set up as a ping function which returns a promise object. The promise is resolved or rejected based on whether the ping worked or failed.
I wish to have this function running in a loop, so regardless of whether the ping is successful or not, the next ping is then fired after a certain amount of time after the previous request has been resolved.
The problem is not this task itself, but I'm concerned about my implementation. I believe it will cause a stack overflow eventually.
Here's some code to see what's happening:
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]);
I've tried to limit the code just to reflect the scope of the following questions:
Will this eventually cause a stack overflow? Is there a pattern which prevents overflows for callback-based loops while using promises?
No stack overflow here. setTimeout
is an asynchronous function: it schedules the function to be run but does not invoke it immediately. Since the repeated call to doEvery
is inside the callback for setTimeout
, this will ensure that it does not overflow.
Here is an example of what the deepest stack might look like at various points:
[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
So as you can see, every time you wait on a promise or a timeout, control is returned to the event loop. When the event (such as the timeout is reached or a ping response is received), the event loop then invokes the callback registered for that event.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With