CIT041J Index > Lecture Notes - Timers

CIT041J Lecture Notes - Timers

One-shot timers

JavaScript allows you to set a “timer” so that an action will occur at a predetermined time in the future. A one-shot timer is like the timer on your microwave oven; you set it and go about your business. When the timer hits zero, the microwave beeps and you get your food. Here is the general model in JavaScript:

timerVariable = window.setTimeout( "JavaScript code", milliseconds );

The first parameter is the code you wanted to execute when the timer goes off. This can be one JavaScript statement or many JavaScript statements separated by semicolons. Usually it will be a function call of some sort.

The second parameter is the number of milliseconds to wait before taking the action, so if you are thinking in terms of seconds, be sure to multiply the number of seconds by 1000.

The timer variable is a global variable that contains the timer’s ID (a number assigned by the browser to keep track of a timer’s status).

Here is an example that will turn the screen background light green five seconds after you click a form button. Look at the JavaScript:

var timer;

function setFutureEvent( )
{
    timer = window.setTimeout( "document.bgColor='#ccffcc';", 5000 );
    window.status = "Timer has been set";
}

Notice that the window.status is set immediately after you click the button. Setting a timer does not cause your program to wait. It just sets the “kitchen timer” and then your program proceeds directly to the next statement. The browser keeps track of the time, and when the timer expires, the browser executes the JavaScript code you specified as the first parameter.

Of course, there’s no law that says the JavaScript code has to be a single statement; it can be multiple statements separated by semicolons as in this second example, which will set the background color and reset the status bar.

var timer;
function setFutureEvent( )
{
    timer = window.setTimeout(
        "document.bgColor='#ccffcc'; window.status=''",
        5000 );
    window.status = "Timer has been set";
}

...or it could be a call to another function, as in this example.

var timer;

function changeScreen( )
{
    document.bgColor = "#ccffcc";
    window.status = "";
}

function setFutureEvent( )
{
    timer = window.setTimeout( "changeScreen()", 5000 );
    window.status = "Timer has been set";
}

The Timer Variable

We’ve been setting the timer variable all this time, but not making any use of it. The reason you need to have it the timer variable is so that you can clear the timer if you want to stop it from going off. (This is like hitting the “clear” button on your microwave before the food is done cooking.)

The next sample program has two buttons; one to change the color in five seconds, the other to clear the timer in case you change your mind. That button uses the clearTimeout() function. After you clear a timer, it’s a good idea to set the timer variable back to null. That way, other functions can tell if the timer is active or not.

function clearTimerAndStatus( )
{
    window.clearTimeout( timer );
    window.status = "";
    timer = null;
}

Something for You to Try

Complete wakeupcall.html, which lets you set a timer for a certain number of minutes. When the timer goes off, you get an alert telling you to wake up. You may use the window.focus() method; it brings the browser window containing the code to the front if you have multiple browser windows or browser tabs open. Here is a solution.

Interval Timers

Frankly, one-shot timers are of limited use. It is more common to have an event that you want repeated at regular intervals, such as a countdown timer, a real-time clock, or a rotating banner ad. Up until Netscape 4.0 and Internet Explorer 4, you only had one-shot timers, and you had to use them to “fake” an interval timer. (We will explore that later in these notes.) All browsers from Netscape 4.0 onwards have the setInterval() function, which follows this model:

timerVariable = setInterval( "JavaScript code", milliseconds );

At every milliseconds interval, the browser will wake up and execute the JavaScript code that you specified. This program will start an interval timer to increment a counter in the status bar at one-second intervals when you click the button in the form. Note that the counter variable must be global; it must be outside any functions. If you put it into the countUp() function, it would be a local variable which would be set to zero every time you entered the function. This is very clearly not what you want.

var intervalTimer;
var counter = 0;

function startCounting( )
{
    intervalTimer = window.setInterval( "countUp()", 1000 );
    window.status = counter;    // show the initial zero
}

function countUp( )
{
    counter = counter + 1;
    window.status = counter;
}

<form name="myForm" action="#">
<input type="button" value="Start counting" 
    onclick="startCounting( )" />
</form>

Doing a “rotating banner ad” is essentially the same code. Instead of having a button click to start the interval timer, you use the onload attribute in the opening <body> tag. The code in the attribute value will be executed when the HTML source is completely loaded. Here is a program which rotates an image every two and a half seconds. View the source to see how it works.

Stopping an Interval Timer

For such things as rotating ads, you want to keep the interval timer going until the user leaves the page. Sometimes, though, you need to stop the repetition. For example, if you had a timer that counts down in the status bar from ten to zero, you could use code like this, but it would be the wrong approach.

function countDown( )
{
    if (counter > 0)
    {
        counter = counter - 1;
        window.status = counter;
    }
}

This is the wrong approach because the counter never stops. The countDown() function will be called every second even after the count hits the ending value; the code just doesn’t do anything. Yes, it does look fine on the screen, but there’s the extra overhead of the browser having to keep the timer active and keep checking for it.

Instead, you want to use the correct approach, which is to clear the interval timer when you hit the ending value. Note that you used setInterval() to start the interval, so you must use clearInterval() to clear it. Using clearTimeout() will not work.

function countDown( )
{
    counter = counter - 1;
    window.status = counter;
    if (counter == 0)
    {
        window.clearInterval( intervalTimer );
        intervalTimer = null;
    }   
}

Something Else for You to Try

Complete annoying_alarm.html, which lets you set a timer for a certain number of minutes and seconds. If the minutes field is empty, treat it as zero. When the timer goes off, the screen background color will switch between yellow and white five times, ending with white, at intervals of one-half second. Here is a solution which does an excessive amount of error-checking of the user input.

Getting the setInterval() effect with setTimeout()

As mentioned previously, there used to be no setInterval(). It is possible to get the same effect using only setTimeout(). Now that intervals exist, you should use them instead of the following method. The only reason we are presenting it is so that you will recognize it when you see older code. Here is the countdown program, done the old way, and the relevant code is here:

var timer;
var counter = 10;

function startCounting( )
{
    timer = window.setTimeout( "countDown()", 1000 );
    window.status = counter;    // show the initial value
}

function countDown( )
{
    counter = counter - 1;
    window.status = counter;
    if (counter == 0)
    {
         window.clearTimeout( timer );
         timer = null;
    }
    else
    {
        timer = window.setTimeout( "countDown()", 1000);
    }
}

The line in bold is the entire trick. When the first timer that was set in startCounting() expires, it calls countDown(). The counter is decremented, and because it is not equal to zero, the else clause sets the timer again for one second in the future.

For those of you who have used a programming concept called recursion: Many books (including an older version of the JavaScript Bible) say that this is a recursive call. No. It isn’t. The countDown() method does not call itself! All it does is set the timer again, and the browser will activate the function in one second.