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