I have a function in javascript:
function test(){
...
if (){
setTimeout(test(), 1000);
}
}
according to the manual, i can call this with:
setTimeout(test(), 1000);
in fact, it calls, but do not wait the 1s. so I try to use it like the following and it works.
setTimeout(function(){test();}, 1000);
Anyone can explain this to me?
Which manual? Calling test() would call things returned by test() and pass it to setTimeout, so unless your test() is returning a function, this won't work.
You could use the anon function alternative, or you can pass it like setTimeout(test, 1000) without the ().
Another bad usage you might find along the way is to pass it as string like:
setTimeout("test()", 1000)
avoid this at all cost, as this is equivalent to calling eval and you'll run into scoping issue sooner or later.
You should be calling with
setTimeout(test, 1000);
and NOT with
setTimeout(test(), 1000);
In other words, the function you want to call after 1000 ms is test, not the result of calling test!
The reason why
setTimeout(function(){test();}, 1000);
works is that the function you call after 1000ms is a function that calls test, which is basically test itself. For lambda calculus geeks, that's called eta-reduction.
setTimeout expects a function reference. When you pass it this:
setTimeout(test(), 1000);
That is passing the result of calling the test function to setTimeout. Instead, pass it the reference to test itself:
setTimeout(test, 1000);
Want to see something fancy?
function test () {
var what_are_you = 'a closure';
return function () {
alert('I am '+what_are_you+'!')
}
}
setTimeout(test(), 1000);
Here, I am returning a function reference from a function call. See the article below for more info on that!
Documentation
setTimeout on MDN - https://developer.mozilla.org/en/DOM/window.setTimeout
Article about functions, function references - http://jszen.blogspot.com/2008/07/function-reference-vs-function-call.html
Related
I have this counter I made but I want it to run forever, it's really simple, what am I doing wrong here?
function timer() {
console.log("timer!")
}
window.setInterval(timer(), 1000)
You used a function call instead of a function reference as the first parameter of the setInterval. Do it like this:
function timer() {
console.log("timer!");
}
window.setInterval(timer, 1000);
Or shorter (but when the function gets bigger also less readable):
window.setInterval( function() {
console.log("timer!");
}, 1000)
setInterval and setTimeout must be used with callbacks, like:
setInterval(timer, 1000);
or unnamed functions:
setInterval( function() { console.log("timer!"); }, 1000 );
Why your code is not working - when you pass a function as argument to another function with brackets e.g. doSomething ( someFunc() ) you are passing the result of the function.
When the function is passed as object e.g. doSomething ( someFunc ) you are passing a callback. This way someFunc is passed as reference and it is executed somewhere in the calling function. This is the same as the pointers to functions in other languages.
A common mistake is to use the these two functions as shown at w3schools. This makes an implicit call to eval.
Numerous examples, on stackoverflow and elsewhere, show setInterval calling a function by name, followed by interval parameter. As in, it makes sense that the following would work:
function sayHi() { window.alert('hello')}
window.setInterval(sayHi, 1000)
Also tried (though this is not the way examples show it)
window.setInterval(sayHi(), 1000)
But it does not (nor any variations of very simple functions). I can only get it to work by "spelling out" the function within the setInterval statement, like so:
window.setInterval(function(){window.alert('hello')}, 1000)
Any information about this much appreciated.
The following code is executing the function sayHi
window.setInterval(sayHi(), 1000)
^
|
+--- The setTinterval function
is receiving an undefined value,
rather than a function.
Because of that, this code works
window.setInterval(sayHi, 1000)
^
|
+--- setTinterval receives a function, that
will be executed in the future.
So, basically, you need to pass a function object to be able to get it works.
Another example is executing the function sayHi() which returns a function:
var id;
function sayHi() {
return function() { // This is the function that setInterval
window.alert('hello'); // will execute in the future.
clearInterval(id);
}
}
var id = window.setInterval(sayHi(), 1000)
The standard parameters for setInterval are a function, and an interval.
window.setInterval(sayHi(), 1000); wouldn't work as sayHi() is not a function, it's undefined. sayHi is a function, not sayHi().
window.setInterval(sayHi, 1000) is the way to do it.
Because sayHi is equal to function(){window.alert('hello')}
window.setInterval(sayHi(), 1000); is the same as window.setInterval(function(){window.alert('hello')}, 1000) ;
After testing, both work, are you getting any errors?
I am trying to invoke a function in my setinterval function like this
function dosomething(variable) {
console.log(variable);
}
setinterval(dosomething(variable), 2000)
The above code only run once and throws an error after the second setinterval call?
I know I can get this to work using anonymous function, but why not this way?
You can use a anonymous function which will call the dosomething method
setInterval(function(){dosomething(variable)}, 2000)
In your case you are calling dosomething and then is passing the value returned by it to the setInterval()
This line
setinterval(dosomething(variable), 2000)
is the same as
var x = dosomething(variable);
setinterval(x, 2000);
Using the debugger you will notice x is undefined
so you get
dosomething(variable);
setinterval(undefined, 2000);
Hence running once and straight away
I want to call function with arguement periodically.
I tried setTimeout("fnName()",timeinseconds); and it is working.
But when I add an arguement it won't work. eg: setTimeout("fnName('arg')",timeinseconds);
You can add an anonymous function:
setTimeout(function() { fnName("Arg"); }, 1000);
Use an anonymous function, like this:
setTimeout(function() { fnName('arg'); }, time);
In general, never pass a string to setTimeout() or setInterval() if you can avoid it, there are other side-effects besides being bad practice...e.g. the scope you're in when it runs.
Just as a side-note, if you didn't need an argument, it's just:
setTimeout(fnName, time);
setTimeout accepts an expression or a function name or an anonymous function but NO () operator.
() will start executing the function immediately and results in setTimeout accept an invalid parameter.
When using setTimeout, you have to put the code you want to execute into a string:
setTimeout('alert("foobar!");', 1000);
However, I want to execute a function to which I have a reference in a variable. I want to be able to do this:
var myGreatFunction = function() { alert("foobar!"); };
// ...
setTimeout('myGreatFunction();', 1000);
(Though in real life, the alert is a lengthier bit of code and myGreatFunction gets passed around as a parameter to other functions, within which the setTimeout is called.)
Of course, when the timeout triggers, myGreatFunction isn't a recognised function so it doesn't execute.
I wish javascript let me do this, but it doesn't:
setTimeout(function() { myGreatFunction(); }, 1000);
Is there a nice way round this?
If you don't need to call myGreatFunction with any arguments, you should be able to pass setTimeout a function reference:
setTimeout(myGreatFunction, 1000);
Also, you should always avoid passing setTimeout code that it needs to evaluate (which is what happens when you wrap the code in quotes). Instead, wrap the code in an anonymous function:
setTimeout(function() {
// Code here...
}, 1000);
See the setTimeout page at the Mozilla Development Centre for more information.
Steve
Who said that it doesn't let you do it?
It does, the code -
setTimeout(function() { myFunction(); }, 1000);
is perfectly valid.