CodingNic

Asynchronous JavaScript

Timers

Asynchronous JavaScript 20 min read

Timers

Objectives

By the end of this chapter, you should be able to:

  • Explain why JavaScript doesn’t run top to bottom when a timer is involved
  • Delay code with setTimeout()
  • Repeat code with setInterval()
  • Cancel a pending timer with clearTimeout() or clearInterval()

💡 Why this matters: Timers are the simplest possible example of asynchronous code, code that doesn’t finish the moment it’s called. Everything else in this module, promises, async/await, fetching data, all deal with the same basic idea: something that finishes later, not right now.

Delaying Code with setTimeout()

setTimeout(callback, delayInMs) schedules callback to run once, after at least delayInMs milliseconds have passed. It doesn’t pause anything, the rest of your code keeps running immediately.

javascript
console.log("1: start");

setTimeout(() => {
  console.log("3: timeout fired");
}, 1000);

console.log("2: end");

This logs 1: start, then 2: end, then, a second later, 3: timeout fired. Even with a delay of 0, the timeout callback still runs after the currently running code finishes, never in the middle of it. JavaScript finishes everything it’s already doing first, then handles the timer.

Repeating Code with setInterval()

setInterval(callback, delayInMs) works like setTimeout(), except it keeps running every delayInMs milliseconds until you stop it.

javascript
let count = 0;

const id = setInterval(() => {
  count++;
  console.log("tick", count);

  if (count === 3) {
    clearInterval(id);
  }
}, 1000);

This logs tick 1, tick 2, tick 3, once per second, then stops. Without that clearInterval(id) call, it would keep ticking forever.

Canceling a Timer

Both setTimeout() and setInterval() return an id, a value you can hand to clearTimeout() or clearInterval() to cancel it before it fires.

javascript
const id = setTimeout(() => {
  console.log("this never prints");
}, 5000);

clearTimeout(id);
console.log("canceled before it fired");

Canceling only works before the callback runs, calling clearTimeout() after a timeout already fired does nothing (there’s nothing left to cancel). This matters most for things like a “typing…” indicator: start a timer when the user types, and cancel it if they type again before it fires.

Try It

Starter code for all three exercises:

javascript
console.log("Start");
  1. Add a setTimeout() that logs "One second later" after 1000ms. Run the code and confirm "Start" logs before it.
  2. Add a setInterval() that logs "tick" every 500ms, and stops itself with clearInterval() after 4 ticks.
  3. Start a setTimeout() that logs "Too late" after 2000ms, then immediately call clearTimeout() on it. Confirm the message never logs.

Recap

  • setTimeout(callback, delayInMs) runs callback once, after at least that many milliseconds.
  • setInterval(callback, delayInMs) runs callback repeatedly, every that many milliseconds, until stopped.
  • Both return an id. clearTimeout(id) or clearInterval(id) cancels a pending timer, but only before it has already fired.
  • Code after a setTimeout() or setInterval() call keeps running immediately, it doesn’t wait for the timer.

Next lesson: callbacks, the pattern timers already use, and what happens when you need several of them in sequence.