Javascript Periodical Executer
👉 Whoa! Please note that this post is 17 years old. The views expressed within might have become outdated.
When writing Javascript, you sometimes want to execute a certain function repeatedly (for instance, when creating a bit of animation, or when pinging for new messages in an AJAX chat application).
This involves calls to setTimeout
or setInterval
and usually repeatedly checking some conditions.
For simple, periodically executed calls to your custom functions, I have now written an easy extension to the Function
prototype.
How does it work?
First of all, this is the complete code, which you can copy or download here:
Function.prototype.executePeriodically = function (){
var s = this;
if (typeof arguments[0].callee != 'undefined'){
var arquments = arguments[0];
} else {
var arquments = arguments;
}
var delay = arquments[0];
var timesToExecute = arquments[1];
this.__INTERVAL__ = null;
var args = [];
for (var i=2; i<arquments.length; i++){ args.push(arquments[i]); }
s.apply(this,args);
if (this.__INTERVAL__)
clearTimeout(this.__INTERVAL__);
if (--timesToExecute > 0){
this.__INTERVAL__ = setTimeout (function (){
arquments[1] = timesToExecute;
s.executePeriodically(arquments);
},delay);
}
return s;
}
Especially for beginning Javascript programmers, this may look mighty complex, but I’ll walk you through it line by line.
Function.prototype.executePeriodically = function (){
First of all, this functionality extends the Function
prototype, so you can use it as if it was natively supported by Javascript.
var s = this;
if (typeof arguments[0].callee != 'undefined'){
var arquments = arguments[0];
} else {
var arquments = arguments;
}
On the first line, I save a reference to this
, as to not get confused later on. Also, I check to see if the first entry in the arguments
array has a callee
property. This is important later on, when I’m going to call the function for the second (or more) time. Based on this if
statement, I create the arquments
variable, which contains either the arguments
array, or the first entry thereof. Don’t worry, you’ll see why later on.
var delay = arquments[0];
var timesToExecute = arquments[1];
this.__INTERVAL__ = null;
Then, I fetch and create some useful variables, namely the delay between execution cycles and the maximum number of times this should be executed. Also, I create a property to contain our interval.
var args = [];
for (var i=2; i<arquments.length args.push="" i="" s.apply="">
This code creates an array with the remaining parameters. Remember, the first two are the interval and the maximum number of executions you wish to invoke.
Then, using apply ()
, we execute the original function for the first time. I use apply ()
here for the simple reason I can toss in the parameters as an array. This is useful because I can not know at this point how many parameters the code using this functionality is going to give me. With execution number one done, we’re almost there. I will now check to see if we have to execute the function again.
if (this.__INTERVAL__)
clearTimeout(this.__INTERVAL__);
First, just to make sure, I cancel any interval that’s currently running.
if (--timesToExecute > 0){
this.__INTERVAL__ = setTimeout (function (){
arquments[1] = timesToExecute;
s.executePeriodically(arquments);
},delay);
}
Next, I check to see if (timesToExecute
minus 1) is larger than zero (note that the decrement operator --
automatically subtracts 1 from the variable). If so, I first replace timesToExecute
with its new, decremented version in the arquments
array, after which I execute the function again (through executePeriodically()
).
This time, however, I cannot send every single parameter, because, again, I do not know how many parameters will eventually be thrown in by developers using this functionality. Therefore, I send only a single parameter: the entire arquments
array.
Remember the first, somewhat odd, if
statement? After the first time the function gets executed, the only parameter to this function will be the previously used arquments
array. This array will have a callee
property (which references the executing function), so by checking for that property, my logic will know whether to use the genuine arguments
array, or the first entry of that array, which finally results in pretty much the same array of parameters.
Important to note is the decrementing of the timesToExecute
variable. Because this variable is getting subtracted by 1 every execution cycle, eventually it will become zero and the code knows there’s no need to execute the function again.
How to use?
Easy! Let’s say you have a simple function which creates a paragraph containing the text “Bar”:
function foo (str){
var div = document.getElementById('dump');
var p = document.createElement('p');
p.appendChild(document.createTextNode(str));
div.appendChild(p);
}
If you want to execute this function 5 times, every 500 milliseconds, you can do this:
window.onload = function (){
foo.executePeriodically(500,5,'bar');
}
Simple, eh?
Extending
Of course, this function might be a bit too simple. For instance, most of the time you want to check certain conditions for every iteration, instead of executing a function a set number of times. It would be easy to extend the functionality to except another parameter containing a certain expression, and write some check to see if the expression evaluates to true
. Also, some kind of cancelExecution
method would be nice, so you can quit execution from outside the function.
I might write that some other day :-)