Skip to content Skip to sidebar Skip to footer

Are There Memory Leaks With Javascript Call A Function In A Callback Recursively?

Let's say, for example, you are writing a program that waits for a message on a queue, handles it, and then waits for the next message, and this goes on forever. In a language like

Solution 1:

No, recursive function calls do not cause memory leaks in Javascript.

The only memory used by a function call is a bit of stack space (so the interpreter knows where to go when the function returns) and whatever memory is used by the scope object of the function (e.g. the local variables). That stack memory is completed returned to the system when the function call returns. It does not leak.

In JavaScript, with asynchronous callbacks, the initiating function has already returned and thus the stack has been cleared long before the asynchronous callback has been called so there is no build up of the stack.

There will be a function scope object in memory until the callback is done and that is important and is required to allow the inline callback to have access to the variables declared in its parent scope. As soon as the callback is done (not reachable any more), that scope object will be garbage collected. Unless you are doing something unusual such as allocated giant strings or buffers in that temporary scope, the memory usage of that scope should not be an issue.

As for retrieving many messages from one initial function call and then repeated calls of the same callback, keep in mind that the parent function is just executed once and just one scope object is allocated no matter how many times the callback is called so there is no build up of memory for each time the callback is called. The callback itself will get a new function scope each time it is called, but since the callback itself doesn't trigger any asynchronous calls, that scope object will be temporary and will be eligible for garbage collection as soon as the callback is done with its work and returns.

If you chain/embed asynchronous operations inside each other, then additional scope objects will be retained for the duration of the asynchronous operation, but this is how Javascript works and is what offers the features of having access to your parent scope. In practice, it has not generally proven to be a memory issue. Scope objects by themselves are relatively compact objects (one is created for nearly every function call) so as I said above as long as you don't put giant buffers or giant strings/arrays into a persisting scope, the memory usage is usually not relevant.


Also keep in mind that when you call processMessage() again from within the asynchronous callback that isn't the kind of recursion that you might generally think of because the previous function call to processMessage() has already returned and the stack has completely unwound before the asynchronous event triggered the callback. So, there is no stack build-up in this case. This is because asynchronous operations in Javascript all run through an event queue. When an asynchronous operation is ready to trigger an action, it puts an event in the Javascript event queue. That event is only processed when the current thread of JS operation has finished and completely unwound. Only then does the JS interpeter look in the event queue to see if there is something else to do. As such, the stack is always completely unwound before the next asynchronous operation is triggered.

For more info on how this works and a number of reference articles on the JS event queue (which works the same in node.js that it does in the browser), see this article:

How does JavaScript handle AJAX responses in the background?

This is one of the reasons that Joyent calls node.js an "an event-driven, non-blocking I/O model" right on the node.js home page.


Solution 2:

Functions aren't allocated on the stack. The callback function will be garbage collected after it's been used unless a reference is kept for some reason. Your code should be just fine!


Solution 3:

here is great description abut nextTick()

function processMessage() {
    waitForMessage(function(msg) {
        // handle msg or error here
        process.nextTick(processMessage;
    }); 
}

Post a Comment for "Are There Memory Leaks With Javascript Call A Function In A Callback Recursively?"