Use JavaScript timing events (setTimeout, setInterval)

Programming for the Web – Topic 21 (Cambridge IGCSE/A‑Level IT 9626)

Learning Objective

Students will be able to use JavaScript timing events (setTimeout and setInterval) to create dynamic, accessible, and secure web pages, and to integrate these techniques with the broader web‑development concepts required by the syllabus (HTML5, CSS, DOM, accessibility, security, performance, and cross‑topic applications such as mail‑merge, graphics/animation and web‑programming).


1. Web Fundamentals Refresher

  • HTML5 document structure<!DOCTYPE html>, <html>, <head>, <body>.
  • Semantic elements<header>, <nav>, <main>, <section>, <footer>.
  • Linking external resources<link rel="stylesheet" href="style.css"> and <script src="script.js"></script>.
  • Basic CSS – selectors, display, position, background, media queries for progressive enhancement.

2. JavaScript Basics Required for Timers

  • Variableslet, const, var (scope reminder).
  • Control structuresif / else, for, while.
  • Functions – declaration, expression, arrow functions, and the importance of passing a function reference (not a call) to a timer.
  • Objects & arrays – useful for storing timer IDs or data for a slideshow.

3. The Event Loop, Task Queues and Timing Events

The browser executes JavaScript on a single thread. After each piece of code runs, the engine checks the task queue. Timer callbacks are placed on this queue once their delay has elapsed. When the call stack is empty, the event loop moves the next task from the queue to the stack and executes it. Because the queue also holds micro‑tasks (e.g., promise callbacks), a timer callback may be delayed further if micro‑tasks are pending.

Simplified flow of a timer event through the event loop

4. Mapping Timer Features to Syllabus Outcomes

  • Dynamic content – Timers allow content to change after the page loads (e.g., clocks, slideshows).
  • Accessibility – Use aria-live regions and provide pause controls so users with disabilities can control automatic updates.
  • Security – Properly clearing timers and sanitising DOM updates prevents XSS and other timing‑based attacks.
  • Performance – Understanding drift, recursive setTimeout, and requestAnimationFrame helps students write efficient code.
  • Cross‑topic integration – Timers can be combined with mail‑merge (delayed preview), graphics/animation (canvas updates), and web‑programming (polling a server).

5. setTimeout() – One‑Off Delayed Execution

Syntax

let id = setTimeout(callback, delay, …args);
  • callback – a function reference (named, anonymous, or arrow).
  • delay – time in milliseconds (minimum 0; browsers clamp very small values to ~4 ms for nested timers).
  • …args – optional arguments passed to callback when it runs.
  • Returns a numeric timer identifier used by clearTimeout.

Example – Show a message after 2 seconds

function showMessage() {
    alert('Hello after 2 seconds!');
}
setTimeout(showMessage, 2000);

Clearing a timeout

let timerId = setTimeout(() => console.log('Will not run'), 5000);
clearTimeout(timerId); // cancels the pending callback

Exam tip

In an exam, you may be asked to identify a security flaw such as:

setTimeout(() => {
    document.body.innerHTML = userInput; // ❌ unsafe – XSS risk
}, 1000);

Correct approach: sanitise userInput or use textContent instead of innerHTML.


6. setInterval() – Repeated Execution

Syntax

let id = setInterval(callback, interval, …args);
  • Works like setTimeout but automatically repeats every interval milliseconds.
  • Stop it with clearInterval(id).

Example – Simple digital clock

function updateClock() {
    const now = new Date();
    document.getElementById('clock').textContent = now.toLocaleTimeString();
}
let clockId = setInterval(updateClock, 1000); // update every second

Stopping the clock

clearInterval(clockId); // stops the periodic updates

Drift note

setInterval does not account for the time taken by the callback. Over many iterations the schedule can slip (drift). For more accurate timing use a recursive setTimeout pattern (see Section 13).


7. requestAnimationFrame() – Animation‑Friendly Alternative

  • Calls the supplied callback before the next repaint (typically 60 fps).
  • Synchronises with the display refresh, giving smoother animations and lower power consumption.
  • Not suitable for non‑visual tasks such as polling a server.

Example – Moving a box across the screen

let start = null;
const box = document.getElementById('box');

function step(timestamp) {
    if (!start) start = timestamp;
    const progress = timestamp - start;
    box.style.transform = `translateX(${progress / 5}px)`;
    if (progress < 2000) { // stop after 2 seconds
        requestAnimationFrame(step);
    }
}
requestAnimationFrame(step);

8. Comparison of Timing APIs

Feature setTimeout setInterval requestAnimationFrame
Execution pattern Single call after the delay Repeated calls at the interval Repeated calls synced to the display refresh
Typical use‑case Delays, one‑off actions, debouncing Clocks, polls, simple non‑visual loops Visual animations, canvas updates, CSS transitions
Stopping mechanism clearTimeout(id) clearInterval(id) Cancel by not calling requestAnimationFrame again
Potential drift None (single execution) Can accumulate; mitigate with recursive setTimeout None – runs just before each repaint
Minimum delay ~4 ms for nested timers ~4 ms for nested timers Controlled by the monitor’s refresh rate (≈16 ms for 60 Hz)
Return value Numeric timer identifier Numeric timer identifier Numeric request ID (can be cancelled with cancelAnimationFrame)

9. DOM Manipulation with Timers

9.1 Updating page content – Live clock with ARIA

<div id="clock" aria-live="polite">--:--:--</div>
<button id="pauseClock">Pause</button>
<script>
let clockId = null;
function updateClock() {
    const now = new Date();
    document.getElementById('clock').textContent = now.toLocaleTimeString();
}
function startClock() {
    if (!clockId) clockId = setInterval(updateClock, 1000);
}
function pauseClock() {
    clearInterval(clockId);
    clockId = null;
}
document.getElementById('pauseClock').addEventListener('click', pauseClock);
startClock(); // start automatically
</script>

9.2 Changing style repeatedly – Colour Changer with Pause

function randomColour() {
    const r = Math.floor(Math.random()*256);
    const g = Math.floor(Math.random()*256);
    const b = Math.floor(Math.random()*256);
    return `rgb(${r},${g},${b})`;
}
let colourId = null;
function startColourChange() {
    colourId = setInterval(() => {
        document.body.style.backgroundColor = randomColour();
    }, 3000);
    // stop automatically after 30 seconds
    setTimeout(() => clearInterval(colourId), 30000);
}
function pauseColourChange() {
    clearInterval(colourId);
    colourId = null;
}
document.addEventListener('DOMContentLoaded', startColourChange);

10. Event Handling and Timers

Timers are often combined with user‑generated events such as clicks or form input.

Example – Start / Stop a slideshow

<button id="start">Start</button>
<button id="stop">Stop</button>
<img id="slide" src="img1.jpg" alt="slideshow image">

<script>
const images = ['img1.jpg','img2.jpg','img3.jpg'];
let index = 0;
let slideId = null;

function showNext() {
    index = (index + 1) % images.length;
    document.getElementById('slide').src = images[index];
}

document.getElementById('start').addEventListener('click', () => {
    if (!slideId) slideId = setInterval(showNext, 2000);
});

document.getElementById('stop').addEventListener('click', () => {
    clearInterval(slideId);
    slideId = null;
});
</script>
  • Using addEventListener keeps JavaScript separate from HTML – a key principle of progressive enhancement.
  • Always clear timers when a component is removed or the page is unloaded (see Section 12).

11. Asynchronous Programming Context

  • CallbackssetTimeout and setInterval are classic callback‑based APIs.
  • Promises & async/await – timers are often wrapped in promises for cleaner flow:
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async function demo() {
        console.log('Start');
        await delay(2000);
        console.log('Two seconds later');
    }
    demo();
  • Fetch API & polling – combine a timer with network requests:
    function poll(url, interval) {
        const id = setInterval(async () => {
            const resp = await fetch(url);
            const data = await resp.json();
            console.log(data);
        }, interval);
        return id; // caller can clearInterval when done
    }
    const pollId = poll('data.json', 5000);
    // later: clearInterval(pollId);
    

12. Accessibility & Progressive Enhancement

  • Provide ARIA live regions for automatically updating content (e.g., clocks, news tickers).
  • Offer a “Pause” or “Stop” control so users who are sensitive to motion can halt updates.
  • Avoid relying solely on colour; include text or icons as fallbacks.

Accessible clock example (see Section 9.1)


13. Security Considerations

  • Content Security Policy (CSP) – restricts inline scripts and helps prevent malicious timer‑driven code.
  • Never insert un‑trusted data into innerHTML inside a timer callback – this creates an XSS risk.
  • Clear timers when navigating away from a page to avoid “orphaned” callbacks that could manipulate a stale DOM.

Exam tip

Identify the vulnerability in the snippet below and suggest a safe alternative:

setTimeout(() => {
    document.body.innerHTML = userSuppliedHTML; // ❌ unsafe
}, 0);

Safe version:

setTimeout(() => {
    const div = document.createElement('div');
    div.textContent = userSuppliedHTML; // treats content as plain text
    document.body.appendChild(div);
}, 0);

14. Performance & Accuracy

  • DriftsetInterval does not account for the time taken by the callback; over many cycles the schedule can slip.
  • Recursive setTimeout pattern for more accurate timing:
    function tick() {
        // …do work…
        setTimeout(tick, 1000); // schedule next tick after work finishes
    }
    tick();
  • For visual animations, prefer requestAnimationFrame (Section 7) because it is synchronised with the display refresh rate.
  • Avoid creating a large number of intervals; each consumes a separate timer handle and can degrade responsiveness.

15. Cross‑Topic Links (A‑Level Integration)

Timelines are not isolated; they can be combined with other A‑Level topics:

  • Mail‑merge (Topic 18) – Use setTimeout to display a preview of a merged document a few seconds after the user clicks “Generate”.
  • Graphics & Animation (Topic 19) – Drive canvas drawings with requestAnimationFrame or a fast setInterval loop; timers also enable sprite animation frames.
  • Web programming (Topic 21) – Implement server polling, live chat updates, or auto‑refreshing dashboards using setInterval combined with the Fetch API.

16. Common Pitfalls & Best Practices

  1. Minimum delay – Browsers enforce a minimum of ~4 ms for nested timers; very short delays are rounded up.
  2. “Timer hell” – Keep timer IDs in variables and clear them when they are no longer needed (e.g., component destroy, window.unload).
  3. Scope of this – Arrow functions preserve lexical this; regular functions may need .bind(this) when used as callbacks.
  4. Argument passing – Modern browsers support extra arguments after the delay; for older browsers wrap the call in an anonymous function.
  5. Memory leaks – Un‑cleared intervals keep references to DOM nodes, preventing garbage collection.
  6. Accessibility – Always provide a way to pause or disable automatic updates.
  7. Security – Never execute user‑generated code inside a timer; use CSP and sanitise any data inserted into the DOM.

17. Testing & Debugging Timers

  1. Open DevTools → Sources → Call Stack to see where a timer callback originates.
  2. Use console.log with timestamps to verify drift:
    console.log('Tick', new Date().toISOString());
  3. In the Network panel, confirm that repeated AJAX calls (if any) are sent at the expected interval.
  4. Add a window.addEventListener('unload', …) handler that clears all active timers.

18. Practice Questions

  1. Colour changer – Write a script that changes the page’s background to a random colour every 3 seconds and automatically stops after 30 seconds. Include a “Pause” button that can halt the colour changes at any time.
  2. Loop‑closure problem – Explain why the following code does not log the numbers 1‑5 at one‑second intervals and provide a corrected version:
    for (var i = 1; i <= 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, i * 1000);
    }
  3. Debounce implementation – Using setTimeout, create a debounce function that limits how often a handler runs while a user types in a text field. Demonstrate it with a live‑search field that logs the query after the user stops typing for 300 ms.
  4. Polling a server – Write a function poll(url, interval) that fetches JSON data from url every interval milliseconds and logs the result. Show how to stop the polling after 20 seconds.
  5. Accessibility audit – Given a snippet that updates a news ticker every 2 seconds, identify any accessibility shortcomings and rewrite the code to comply with ARIA best practices and include a pause control.

Create an account or Login to take a Quiz

42 views
0 improvement suggestions

Log in to suggest improvements to this note.