JavaScript Tutorial · Asynchronous JavaScript · Lesson 31 of 44

JavaScript Callbacks and Timers

setTimeout, setInterval and the event loop.

JavaScript runs one thing at a time

JavaScript has a single main thread. Slow work — timers, network requests, file reads — is handed off, and a callback runs later when the result is ready. The event loop decides what runs next.

setTimeout

setTimeout(fn, ms) runs fn once after at least ms milliseconds. Notice the order of the output:

Example 1Try it yourself
console.log("1. start");
setTimeout(() => console.log("3. timeout (after 0 ms)"), 0);
console.log("2. end of script");

Output

1. start
2. end of script
3. timeout (after 0 ms)

Even with a 0 ms delay, the callback waits until the current code has finished.

setInterval

setInterval(fn, ms) repeats until you call clearInterval:

Example 2Try it yourself
let ticks = 0;
const id = setInterval(() => {
  ticks++;
  console.log("tick", ticks);
  if (ticks === 3) {
    clearInterval(id);
    console.log("stopped");
  }
}, 100);

Output

tick 1
tick 2
tick 3
stopped

Callback hell

Nesting callbacks inside callbacks quickly becomes unreadable ("the pyramid of doom"). Promises and async/await, covered next, solve that. Test your understanding with the event loop output puzzle.

Test yourself

When does a setTimeout(fn, 0) callback run?

  1. Immediately, before the next line
  2. After the current code finishes
  3. Never
  4. Exactly 0 ms later, interrupting the code
Show answer

Answer: After the current code finishes

Practice next