2

I am reading this article on javascript optimization. Article

I came across this section and it tells me when a leak occurs. But I can't find what is the proper way to call it so a leak does not occur. Here is the section I am interested in.

One of the worst places to leak is in a loop, or in setTimeout()/setInterval(), but this is quite common. Consider the following example.

var myObj = {
 callMeMaybe: function () {
 var myRef = this;
 var val = setTimeout(function () { 
 console.log('Time is running out!'); 
 myRef.callMeMaybe();
 }, 1000);
 }
};

If we then run:

myObj.callMeMaybe();

to begin the timer, we can see every second "Time is running out!" If we then run:

myObj = null;

The timer will still fire. myObj won’t be garbage collected as the closure passed to setTimeout has to be kept alive in order to be executed. In turn, it holds references to myObj as it captures myRef. This would be the same if we’d passed the closure to any other function, keeping references to it.

It is also worth keeping in mind that references inside a setTimeout/setInterval call, such as functions, will need to execute and complete before they can be garbage collected.

The question is: How do you do this properly so that you don't leak? Is it as simple as calling clearInterval? And does this leak once or leak once per interval

asked Jun 25, 2014 at 16:34
1
  • Keep in mind that val is not available outside functions, so you need some factory to manage all timers in application. To call clearInterval you need know the value of val Commented Jun 25, 2014 at 16:46

1 Answer 1

1

I wouldn't call this a memory leak in any fashion - it's simple garbage collection doing what it's supposed to. There is no more "proper" way to do it.

The object that was initially pointed to by myObj is still in use as long as your timer is running. A garbage collector will free it as soon as there are no more references to it. Setting myObj = null clears one reference to it, but your ongoing timers have another reference in myRef so it can not be garbage collected until ALL references to it are gone.

Yes, if you stop your timer and set myObj = null, then there will be no more references to the object and the GC will get rid of it. Keep in mind that you will need to provide access to the timerid if you want to stop the timer from the outside because no outside code can get to val where you have it stored now.


If you had lots of other data in myObj that the timer did not need access to and you were trying to allow that data to be freed while the timer continues to run, then you can either keep the same structure you have now, but clear that other data from the object (either remove the properties or set the properties to null) or you can change the structure of your code so that the recurring timer is launched with a separate function call and doesn't have to keep a reference to the object in order to call a method.

In other words, if your timer method needs access to the object, then the object is correctly kept alive by the garbage collector. If the timer method doesn't need access to the object, then you should run the recurring timer some other way that doesn't repeatedly call a method on the object - allowing the object to be garbage collected.

answered Jun 25, 2014 at 17:02
Sign up to request clarification or add additional context in comments.

5 Comments

Do you have to explicitly call clearTimer or is it automatically cleared in the case of setTimeout?
@Leo: You can have multiple timeouts set, so setTimeout won't mess with the one that's already set. You'd have to call clearTimeout. Alternatively, you could check whether myObj is equal to myRef, and simply not call setTimeout again in that case. (You should have access to myObj via the closure.) But note that if you do it that way, then if you want an additional timeout, you'd have to store it in a different variable.
@Leo: The callback will be released once it fires (unless, of course, you reattach it by calling setTimeout again). So if that's the only thing holding a reference to it, it'll become garbage.
@cHao Sorry my comment wasn't clear. What I meant was does setTimeout release the reference after it has finished executing the callback function. I would expect it to but I am not sure.
@Leo - The reference will be automatically released when setTimeout() finishes as long as you don't call setTimeout() again, creating a new reference. You don't have to call clearTimeout() after setTimeout() has fired.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.