Passing parameters to a function called with setTimeout
When creating my news ticker plugin, I came across a slight complication when using setTimeout() to calling a function which needed parameters passed to it.
Not having had much call to use setTimeout in the past, I simply put:
setTimeout(myFunction(parameter),myTimeout);
but that doesn’t work. An apparent solution (until tried in Internet Explorer) is:
setTimeout(myFunction,myTimeout,parameter);
It wasn’t as easy as I expected to find out how to get around this, but it turns out that all is needed is a “closure”:
setTimeout(function(){myFunction(parameter)},myTimeout);
Closures are arguably the great secret of Javascript: the way variable scope stacks get frozen at the point of closure (and hence variables persist within the closure) is quite subtle and catches most out, including me!
Be warned that IEx has a garbage-collector subtlety, though; I think that if you reference a DOM variable in a Javascript closure, then the collection mechanism gets confused and it doesn’t get trashed at the end of the request: eventually this becomes a memory leak. I think it’s because DOM variables and internal JS variables get collected by two different collectors, and they don’t communicate properly about what’s no longer being used.
I think you can fix this by setting the variable to null:
setTimeout(function(){myFunction(parameter); parameter = null},myTimeout);
This explicitly sets the garbage collection in motion.
Comment by J-P Stacey — October 29, 2007 @ 9:15 am
Thanks for that, J-P - I agree they seem to be rather a secret! I’ve added this into the news ticker and put up the new release
Comment by bryan — October 31, 2007 @ 4:37 am
I was pulling my hair out. The books seem to gloss over this like I should have known it and then go on to tell me some obscure thing I’ll never use. I cannot thank you enough!
Comment by Greg — November 7, 2007 @ 1:47 am
This is great. I was getting rather frustrated with IE not accepting the 3rd parameter and could not find a way around it for my code. Now I dont have to.
Comment by Matt — August 7, 2008 @ 8:25 am
Great tip!! I’ve been looking for this solution for a while now. Thanks!
Comment by Jake — August 13, 2008 @ 3:47 am
Thanks for the tip, I found a couple of other solutions which were not idea. The first was to make the function in a string (does not work for objects). The second from M$ was to use global variables (bad bad bad).
Thanks again, you are no bookmarked!
Comment by Ergin — September 17, 2008 @ 2:23 pm
This was very helpful! I was looking for this solution everywhere!
Thanks
Comment by Chris — October 7, 2008 @ 8:17 pm
[...] the ‘variable = null’ is to stop a memory leak as the variable is not deleted as it should be (thanks makemineatriple) [...]
Pingback by Javascript: Passing variables with setTimeout and getting it to work in Internet Explorer - Graphic Euphoria — November 17, 2008 @ 1:54 pm
great reminder … closure is the answer …
Comment by willowdan — November 26, 2008 @ 9:53 am
Thanks for the tip!
Rico
Comment by Rico — November 26, 2008 @ 3:22 pm
Thank you!
Not only did you give a lucid explanation of this setTimeout dilemma, you cleared up the ‘closure’ concept for me. All in 100 words or less.
I have several other ‘tutorials’ and they all dove headfirst into ‘here, look at this code’ and never got around to the heart of the matter.
Comment by Don Bevis — December 6, 2008 @ 2:20 am
Don’t want to spam, just to say a sincere Thank you!
Comment by Viper — December 6, 2008 @ 10:00 pm
Thank you. Cannot express my feeling in words. I was getting no where since last 2 days and this blog made my day.
Thank you. You Rock!!
Comment by Ankit Bansal — December 17, 2008 @ 1:06 pm
Great tip!! I’ve been looking for this solution for a while now. Thanks!
Comment by coolpositive — January 8, 2009 @ 11:32 am
Thanks a lot! I’ve been googeling for hours for this solution.
Comment by Esger — February 3, 2009 @ 10:57 pm
Thanks a lot.
F*ck Explorer.
Comment by cadeyrn — February 5, 2009 @ 2:20 pm
[...] (thanks makemineatriple) [...]
Pingback by Javascript: Passing variables with setTimeout and getting it to work in Internet Explorer « Graphic Euphoria — February 12, 2009 @ 2:06 pm
Thank you very very much.
Comment by AV — February 23, 2009 @ 3:40 pm
Well done buddy!
You ARE the man - thanks. Victor.
Comment by Victor — February 27, 2009 @ 3:23 pm
Great article! saved me a lot of time.
Thanks a lot!!
Comment by Dave — March 2, 2009 @ 4:24 pm
Great help! Thanks a lot!! Searched a solution for a whole day..Finally got it
Comment by Sangeetha — March 9, 2009 @ 11:15 am
I found something else that seems to work. Whenever I use setTimeout, the syntax looks like this:
setTimeout(”Myfunction(parameter)”,timeout)
For me what’s evolved is the manipulation of the string part of the function–the new function and parameter(s), which are in quotes. I can pass a parameter by writing the function like this:
setTimeout(”Myfunction(” + parameter + “)”, timeout)
Seems to work fine, at least at this point. Anybody have any comments on this?
Comment by Rick — March 13, 2009 @ 4:00 pm
@Rick,
Maybe I’ve misread something, but the following code doesn’t work, while the commented-out line, which uses the closure, is fine:
$(document).ready(function() {
var p1 = 'one';
var p2 = 'two';
//setTimeout(function(){test(p1,p2);},400);
setTimeout("test("+p1+")", 400);
});
function test(param,param2) {
alert(param);
alert(param2);
}
I’d suggest that, any other considerations aside, the closure approach is more manageable syntax, particularly where several parameters are needed.
Bryan
Comment by bryan — March 28, 2009 @ 4:38 am
Thanks a bunch partner. I had been searching for this for a couple of hours. Whoa, got to git back to the ranch.
Comment by Cowboydan — April 7, 2009 @ 11:28 pm
You are top result for this google query:
javascript pass parameters to setTimeout
… THANK YOU for being top result!
Funny enough I’d done what you did but wasnt sure why it was working, and was looking for the “proper” way to do it… I guess this was the proper way!
Comment by BladeMcCool — April 9, 2009 @ 8:39 pm
Finally! OMG! Thanks!
Comment by Anonymous — April 10, 2009 @ 5:15 am
@23 Bryan,
That code is never going to work because you have not written it correctly.
Look at setTimeout(”test(”+p1+”)”, 400);
expand it yourself and you get
setTimeout( test(one), 400);
test(one) is not valid syntax - unless one is defined as a variable - which it is not.
You probably meant setTimeout(”test(’ “+p1+” ‘)”, 400);
Where there are some extra quotes to yield test(’one’).
Even then, it probably doesn’t do what you expect.
Comment by gazhay — June 1, 2009 @ 4:25 pm
@gazhay - you’ve misread my comment:
I declared that the code posted *didn’t* work (in response to Rick - comment 22), but that using my commented-out line *does* work.
Comment by bryan — June 3, 2009 @ 9:11 pm