I was reading an answer on StackOverflow here that explained how to use setTimeout to create a sort of recurring loop on a webpage. However, I am wondering why setTimeout requires an anonymous function to work. Consider the following code:
trainingTimer(60,0);
function trainingTimer(duration,c) {
document.getElementById("timer").innerHTML = "Time left: "+(duration-c);
if(duration==c) {
alert("Time is up!");
}
else {
window.setTimeout(trainingTimer(duration,c+1),1000);
}
}
I wrote this based off the answer that I linked above, however when it runs it loops through all 60 trainingTimer
calls at once, and immediately displays "Time left: 0" on my web page. However, if I modify
window.setTimeout(trainingTimer(duration,c+1),1000);
and wrap trainingTimer(duration,c+1)
in an anonymous function like so
window.setTimeout(function() {trainingTimer(duration,c+1)},1000);
then the code works perfectly fine.
I am wondering why I have to wrap a named function inside an anonymous function in order for setInterval to work properly. Thanks for all the help.
This
window.setTimeout(trainingTimer(duration,c+1),1000);
is the same as
var result = trainingTimer(duration,c+1);
window.setTimeout(result,1000);
It takes the result of the executed method and assigns it.
And since training timer method returns nothing. Your code is basically this
trainingTimer(duration,c+1);
window.setTimeout(undefined, 1000);
The runtime has to evaluate the argument list passed to any function before it calls the function. The first thing you're passing to setTimeout
in this code:
window.setTimeout( trainingTimer(duration,c+1), 1000 );
is the result of calling a function, not the function itself. Wrapping that in a function solves that problem.
The function doesn't have to be anonymous:
function callTrainingTimer() {
trainingTimer( duration, c + 1);
}
// ...
window.setTimeout(callTrainingTimer, 1000);
works too.
Because that's how setTimeout
works. It's first parameter is a function that you want it to run after x milliseconds.
When you do:
window.setTimeout(trainingTimer(duration,c+1),1000);
What you are doing is running trainingTimer
immediately, and sending its return value to setTimeout
.
You need to give it a function, that's why you do:
window.setTimeout(function() {
trainingTimer(duration, c+1);
},1000);
There is a way to do it without a function, but it's NOT recommended.
window.setTimeout('trainingTimer(duration,c+1)', 1000);
This will use eval()
to run the code. This works instead of passing a function, but it is not recommended. eval()
is unsafe, do not use it.