Skip to content

Timers

setTimeout(fn, delay) schedules fn to run as a macrotask after at least delay milliseconds. The delay is a minimum — not a guarantee. If the call stack is busy when the timer fires, the callback waits until the stack is clear.

var id = setTimeout(function() {
console.log('Runs after at least 100 ms');
}, 100);
// Cancel before it fires:
clearTimeout(id);

setInterval(fn, delay) repeatedly schedules fn every delay ms. Use clearInterval to stop it.

var count = 0;
var id = setInterval(function() {
count++;
console.log('tick', count);
if (count >= 3) clearInterval(id);
}, 500);

setTimeout(fn, 0) does not mean “run immediately.” It queues fn as a macrotask. Any pending microtasks (Promise callbacks, queueMicrotask) will run first.

setTimeout(function() { console.log('Timer'); }, 0);
Promise.resolve().then(function() { console.log('Promise'); });
// Output: Promise, then Timer

To schedule a callback before the next macrotask, use queueMicrotask:

queueMicrotask(function() {
console.log('This runs in the microtask queue, before any timer');
});

This demo shows that setTimeout(fn, 0) still runs after a resolved Promise .then, because the timer callback is a macrotask and microtasks drain first.

JavaScript

Output is always: Promise ran first, then Timer ran second.

Is setTimeout(fn, 0) guaranteed to run fn immediately after the current synchronous code?
How do you stop a setInterval from firing again?
Which function schedules a callback in the microtask queue (not a timer queue)?