I am using the setInter开发者_开发百科val()
function to call a function every 20 seconds. However, one thing I noticed is that it the first time setInterval()
actually calls the function is at 20 seconds (and not when setInterval()
is called). Here is my current workaround:
dothis();
var i = setInterval(dothis, 20000);
Is there any way to achieve this without having this duplicate code?
Your method is THE normal way way of doing it.
If this comes up over and over, you could make a utility function that would execute the handler first and then set the interval:
function setIntervalAndExecute(fn, t) {
fn();
return(setInterval(fn, t));
}
Then, in your code, you could just do this:
var i = setIntervalAndExecute(dothis, 20000);
You can make an anonymous function and call it immediately, except you use the setTimeout function instead of setInterval.
(function doStuff() {
//Do Stuff Here
setTimeout(doStuff,20000);
})();
This will execute the function, then call it again in 20 seconds.
Note that depending on the behavior you desire or in some cases for performance, it can be better to use setTimeout over setInterval. The main difference is that setInterval calls that function whenever that timeout is up, REGARDLESS if the last call has finished executing or if an error occurs. Using setTimeout is this fashion ensures that the function finishes its execution before the timer resets. A lot of the tradeoffs are pretty apparent, but it is a good thing to keep in mind as you design your application.
EDIT In response to patrick dw's concern about having the need to cancel the timeout. The best solution is to not use the anonymous function, and just call it after declaration
var timeout;
function doStuff() {
//doStuff
timeout = setTimeout(doStuff,20000);
}
doStuff()
Yes this is similar to what the OP was trying to avoid, but it does removes the need to call the function and then call the setInterval function, so you save a line of code. You can stop and start the function at anytime by:
//Stop it
clearTimeout(timeout);
//Start it
doStuff();
If your dothis
function has no other need for a return value, you can have it return itself.
This will allow you to invoke and pass it at the same time. If the return value is otherwise ignored, it will be harmless.
function dothis() {
// your code
return dothis;
}
var i = setInterval(dothis(), 20000);
Otherwise, you could extend Function.prototype
to give an invoke and return functionality to all your functions:
DEMO: http://jsfiddle.net/ZXeUz/
Function.prototype.invoke_assign = function() {
var func = this,
args = arguments;
func.call.apply( func, arguments );
return function() { func.call.apply( func, args ); };
};
setInterval( dothis.invoke_assign( 'thisArg', 1, 2, 3 ), 20000 );
// thisArg 1 2 3
// thisArg 1 2 3
// thisArg 1 2 3
// ...
This actually enhances things a bit. It lets you pass a set of arguments. The first argument will set the this
value of the function you're invoking, and the rest of the arguments will be passed on as the regular arguments.
Because the function returned is wrapped in another function, you'll have identical behavior between the initial and interval invocations.
精彩评论