views:

157

answers:

4

Hi,

This is the code from another thread. It activates a function only when the user has stopped typing after a set time.

var keyupTimer;
function keyUpEvent(){
   clearTimeout(keyupTimer);
   keyupTimer = setTimeout(sendInput,1000); // will activate when the user has stopped typing for 1 second
} 

function sendInput(){
    alert("Do AJAX request");
}

It works as is. But why does it stop working if I put parenthesis to try to pass variables in this line:

keyupTimer = setTimeout(sendInput,1000); //original code

To

keyupTimer = setTimeout(sendInput(),1000); //with just empty ()

or

keyupTimer = setTimeout(sendInput(var),1000);//or with ('test') or with (var)

with the parenthesis, the delay does not occur and the sendInput function is called immediately. Is this the only format for this particular routine?

TIA

+2  A: 

keyupTimer = setTimeout(sendInput,1000); //original code

This says "Run sendInput after 1000ms";

keyupTimer = setTimeout(sendInput(),1000); //with just empty ()

This says "Run sendInput, capture the return value (which should be a function) and run that after 1000ms".

sendInput is a function, sendInput() is a function call.

David Dorward
Thanks David for the explanation. So what would be the syntax for "Run sendInput(with parameters) after 1000ms"?
jamex
Additionally, reading-between-the-lines: if what the OP really want is to pass a parameter to the callback function then the best, cross-browser way is to use a closure to capture the variable: `setTimeout(function(){sendInput(var)},1000)`.
slebetman
Thank you sletbetman.
jamex
A: 

The first argument for setTimeout is a function reference (i.e. a variable that points to your function). What you provided is a function call. To pass a function with arguments, wrap the function call in an anonymous function. You can pass it directly to setTimeout as an argument since JavaScript functions are first-class objects.

keyupTimer = setTimeout(function() {
    sendInput(var);
}, 1000);

In more verbose, that equals to this:

var callback = function() {
    sendInput(var);
}
keyupTimer = setTimeout(callback, 1000);

The inline pattern has its advantage that it has access to the scope where the setTimeout is called.

If it fits better to you, you could even create a callback factory to pass a function call to setTimeout as @slebetman pointed out.

function callbackFactory (var) {
    return function() {
        sendInput(var);
    }
};
setTimeout(callbackFactory('some_value'), 1000);
Török Gábor
Yet another, better, more verbose example is to use a function factory (just like object factory from factory pattern): `function callbackFactory (var) {return function(){sendInput(var)}}; setTimeout(callbackFactory('some_value'),1000);`
slebetman
Thank you Torok. It is weird, my previous thank you is not showing up.
jamex
+1  A: 

you can try

keyupTimer = setTimeout(function()
{
     sendInput('test');
},1000);

so have an anonymous function as parameter for 'setTimeout'

Alex Pacurar
Thank you Alex.
jamex
A: 

it is also possible to use a string containing javascript code, as a first argument to setTimeout. however, it is strongly discouraged (see comments)

...
/* DON'T DO THIS: */
keyupTimer = setTimeout("sendInput(variable)", 1000) 
...
mykhal
Not a good idea because 1: it is a slippery slope towards quoting hell, 2: the "string code" has to be recompiled every time, 3: every time you compose code from string Jon Skeet kills a kitten
slebetman
Thank you Mykhal. Let me try that, but I will probably use the long hand method so that I remember why.
jamex
Please do not propagate bad practice as answer!
Török Gábor
@slebetman, @[Török Gábor] thanks for pointing it out, i'll mention it. however, i won't delete my answer, since the question contained: *Is this the only format for this particular routine?*
mykhal