4.5 Delaying a Function Call
NN 2, IE 3
4.5.1 Problem
You want a function to run at a
specified time in the near future.
4.5.2 Solution
Use the window.setTimeout(
) method to invoke a function once after a
delay of a number of milliseconds. You essentially set a timer to
trigger a function of your choice. The function is referenced as a
string, complete with parentheses, as in the following example:
var timeoutID = setTimeout("myFunc( )", 5000);
The method returns an ID for the time-out operation and should be
preserved in a global variable. If, at any time before the delayed
function fires, you wish to abort the timer, invoke the
clearTimeout( ) method with the time-out ID as the
parameter:
clearTimeout(timeoutID);
Once the timer is set, other script processing may proceed as usual,
so it is often a good idea to place the setTimeout(
) call as the final statement of a
function.
4.5.3 Discussion
It's important to understand what the
setTimeout( ) method doesn't do:
it does not halt all processing in the manner of a delay that
suspends activity until a certain time. Instead, it simply sets an
internal countdown timer that executes the named function when the
timer reaches zero. For example, if you are creating a slide show
that should advance to another page after 15 seconds of inactivity
from the user, you would initially set the timer via the
onload event handler for the page and the
resetTimer( ) function:
var timeoutID;
function goNextPage( ) {
location.href="slide3.html";
}
function resetTimer( ) {
clearTimeout(timeoutID);
timeoutID = setTimeout("goNextPage( )", 15000);
}
You would also set an event handler for, say, the
onmousemove event so that each time the user
activates the mouse, the autotimer resets to 15 seconds:
window.onmousemove = resetTimer;
The resetTimer( ) function automatically cancels
the previously set time-out before it triggers the
goNextPage( ) function, and then it starts a new
15-second timer.
If the function you are invoking via the delay requires parameters,
you can assemble a string with the values, even if those values are
in the form of variables within the function. But—and this is
important—the variable values cannot be object references.
Parameters must be in a form that will survive the conversion to the
string needed for the first argument of the setTimeout(
) method. Recipe 8.4 demonstrates how you can convey names
of DOM form-related objects as ways of passing an object reference.
The tricky part is in keeping the quotes in order:
function isEMailAddr(elem) {
var str = elem.value;
var re = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
if (!str.match(re)) {
alert("Verify the e-mail address format.");
setTimeout("focusElement('" + elem.form.name + "', '" + elem.name + "')", 0);
return false;
} else {
return true;
}
}
In this example, the focusElement(
) function requires two parameters that
are used to devise a valid reference to both a
form object and a text input
object. Both parameters of the focusElement( )
function are strings. Because the first argument of
setTimeout( ) is, itself, a string, you have to
force the "stringness" of the
parameters to focusElement( ) by way of single
quotes placed within the extended string concatenation sequence. (The
zero milliseconds shown in the example is not a mistake for this
application. Learn why in the discussion for Recipe 8.4.)
If you are looking for a true delay between the execution of
statements within a function or sections of a function, JavaScript
has nothing comparable to commands available in some other
programming languages. But you can accomplish the same result by
dividing the original function into multiple functions—one
function for each section that is to run after a delay. Link the end
of one function to the next by ending each function with
setTimeout( ), which invokes the next function in
sequence after the desired amount of time:
function mainFunc( ) {
// initial statements here
setTimeout("funcPart2( )", 10000);
}
function funcPart2( ) {
// initial statements here
setTimeout("finishFunc( )", 5000);
}
function finishFunc( ) {
// final batch of statements here
}
The related functions don't have to be located
adjacent to each other in the source code. If all related functions
need to operate on the same set of values, you can cascade them as
parameters (provided the parameters can be represented as nonobject
values), or you can preserve them as global variables. If the values
are related, it may be a good reason to define a custom object with
values assigned to labeled properties of that object to make it
easier to see at a glance what each function segment is doing with or
to the values.
Another JavaScript method, setInterval(
), operates much like setTimeout(
), but repeatedly invokes the target function until told to
stop (via the clearInterval( ) method). The second
parameter (an integer in milliseconds) controls the amount of time
between calls to the target function.
4.5.4 See Also
Recipe 8.4 for using setTimeout( ) to keep script
execution synchronized; Recipe 10.11 for a sequence of three
initialization functions that are linked via calls to
setTimeout( ) to keep execution synchronicity in
order; Recipe 12.3 for an example of using a self-contained counter
variable in a repeatedly invoked function to execute itself a fixed
number of times; Recipe 13.9 and Recipe 13.10 for applications of
setInterval( ) in animation.
|