21
Aug

Passing arguments to javascript’s setTimeout() method using closures

Yesterday I ended up having to hack around FCKEditor a bit to “fine tune” it for a project im involved in. The problem was that the html text we needed from the editor was getting back to our app, I didnt touch the code at all except to add a console log (window.console.log()) and tada… it works now. Well it was aparent that the fckeditor was not getting to where i needed to get to fast enough.

Javascript has a method setTimeout, which if you google this, youll find a bunch of related topics on setTimeout, setInterval, and clearTimeout etc… So I went with a setTimeout to simply call the next function i needed 1 millisecond later.

...
setTimeout( doAlert(), 1 );
...
 
function doAlert()
{
	alert();
}

Great! that works… but wait, I need to pass it a few variables. No problem i figured i could just add them inline right?

...
var msg = "Hello World";
setTimeout( doAlert(msg), 1 );
...
 
function doAlert(msg)
{
	alert(msg);
}

Wrong. this wont work in IE which sadly enough we have to support, and my argument that everyone should use firefox or safari just doesnt ever seem to hold water in a big corporation.

So I googled around and came across a post on evolt showing how to add in parameters using closures. Now im not advocating the usage of closures, but I figure in this case it would have to do. So in the end my routine looked a little something like this

...
var msg = "Hello World";
var delay = function() { doAlert(msg); };
setTimeout(delay, 1);
...
 
function doAlert(msg)
{
	alert(msg);
}

this works like a champ on mac and windows in IE, FF, and safari.

There's 5 Comments So Far

  • Thomas
    December 15th, 2008 at 1:11 pm

    There’s an easier way to do this:


    ...
    var msg = "Hello World";

    setTimeout(doAlert, 1, [msg]);
    ...

    function doAlert(msg)
    {
    alert(msg);
    }

    There’s no need for the delay function.

    Furthermore, when passing a reference to a function as the first parameter to the setTimeout method, you’re supposed to pass the reference to the function, not a call to the function.

    e.g.

    // passing a call to the function is incorrect
    var t = setTimeout(someFunction(), 1, argsArray);

    vs.


    // passing a *reference* to the function is correct
    var t = setTimeout(someFunction, 1, argsArray);

    Enjoy,

    Thomas

  • John
    February 6th, 2009 at 12:47 am

    Good comment by Thomas and while I accept your authority on this you’re about the only person out there defining the call this way. Most of the examples I’ve seen pass a “call to the function” and do so in quotes! ie:

    setTimeout(‘someFunction()’,etc)

    And one reference (I can’t remember where) defines that third parameter as an optional definition of the language of the called function!

    Your solution works, of course.

  • John
    February 6th, 2009 at 10:25 am

    Follow-up:

    Well, it seems as though you’re right and wrong Thomas. Firefox does subscribe to what appears to be the standard

    https://developer.mozilla.org/En/DOM/Window.setTimeout

    but IE, of course does not. Thomas’ syntax doesn’t work on IE7 (I tried it).

    An alternative–but less elegant–solution that works in both browsers is to frame the called function/parameters in quotes, thus:

    function called(a,b) {
    alert(a+”-”+b)
    }
    function caller(a,b) {
    setTimeout(‘called(‘+a+’,'+b+’)',2000);
    }

    Later code ….
    caller(1,2);caller(3,4)
    Will show alerts of “1-2″ and “3-4″ after 2 seconds.

  • archerid
    August 27th, 2009 at 1:40 pm

    This was incredibly helpful. I’ve spent an embarrassingly long time trying to track down the right way to pass params through setTimeout. Thanks for posting your method.

  • Trev
    December 1st, 2009 at 5:32 am

    Another version that seems to work is simply:

    setTimeout("doAlert("+msg+")", 1);

    Might get a bit confusing with multiple arguments mind you, but works in IE8, FF3 and Chrome (so presumably also in Safari). Not got IE7 to test it on however.

Share your thoughts, leave a comment!