Suggest an editImprove this articleRefine the answer for “Timer accuracy guarantee”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**No, you cannot guarantee the exact firing time of a timer.** `setTimeout` and `setInterval` never promise that the callback runs exactly after `delay` ms: they only queue the task and guarantee it will not run sooner than `delay`. JavaScript is single threaded, so while the call stack is busy the callback waits; add the browser minimum threshold (about 4 ms), throttling in an inactive tab (up to 1000 ms and more), CPU load and the operating system scheduler. For accuracy, use `performance.now()`, `requestAnimationFrame()` or a timer with drift compensation. ```javascript setTimeout(() => console.log('1s'), 1000); const start = Date.now(); while (Date.now() - start < 3000) {} // it will only fire after 3 seconds ``` **Key point:** a timer delay is a minimum, not an exact time; use `performance.now()` and `requestAnimationFrame()` when you need precision.Shown above the full answer for quick recall.Answer (EN)Image**No, you cannot guarantee the exact firing time of a timer in JavaScript (`setTimeout`, `setInterval` and the like).** The reason is simple: JavaScript is single threaded, and when a timer actually runs depends on the state of the Event Loop and on how busy the call stack is. ## Theory ### TL;DR - A timer only guarantees that the callback will not run **earlier** than the delay you asked for. - While the call stack is busy, the callback waits in the macrotask queue. - Even `setTimeout(fn, 0)` has a minimum delay, about 4 ms in browsers. - In an inactive tab the browser deliberately slows timers down, to 1000 ms and beyond. - `setInterval` does not give even intervals either: a slow callback shifts every later tick. - For precision there are `performance.now()`, `requestAnimationFrame()` and a drift compensating pattern. ### Quick example ```javascript console.log('Start'); setTimeout(() => console.log('Timer 1s'), 1000); const start = Date.now(); while (Date.now() - start < 3000) {} // block the thread for 3 seconds console.log('End'); ``` Result: ```text Start (3 seconds of pause) End Timer 1s ``` Although the timer was set for 1 second, it fired only **after 3 seconds**. Why? Because the engine **could not run it any earlier**, the stack was busy with the loop. ### Why this happens When you call: ```javascript setTimeout(fn, 1000); ``` JavaScript **does not promise** that `fn` runs **exactly after 1000 ms**. It only **queues the task** so that it runs **no earlier** than 1000 ms from now. If the call stack is busy at the moment the timer "fires", the callback waits its turn. ### Minimum delay and throttling Even `setTimeout(fn, 0)` does not start the code "right away", there is still a minimum delay: - in browsers it is usually **4 ms** for nested timers, per the HTML Living Standard; - in Node.js it can be smaller, but it is **not instant** either. On top of that, if the browser tab is inactive the delay can be increased to 1000 ms and more: browsers **save resources**. ### Example with setInterval `setInterval()` **does not guarantee** exact intervals either. If the function inside takes longer than the interval, the calls "accumulate" and run late. ```javascript setInterval(() => { const start = Date.now(); while (Date.now() - start < 1500) {} // block for 1.5 seconds console.log('tick'); }, 1000); ``` The interval is 1 second but the function takes 1.5 seconds, so the ticks arrive with a real delay of 1.5, 3.0, 4.5 seconds and so on. ### Why precision is out of reach | Reason | Explanation | | --- | --- | | **JavaScript is single threaded** | While code is running, other tasks wait | | **Event Loop** | Timers only land in the queue, they do not start instantly | | **Browser limits** | There is a minimum delay, plus throttling in the background | | **CPU load** | Under heavy load timers run later | | **OS scheduler** | JavaScript does not control system time, it only "asks" for the task to run later | ### What you can do If you need **maximum precision**, for example in animation or synchronisation, there are alternatives. 1. `performance.now()` measures precise time in milliseconds, with sub millisecond resolution: ```javascript const start = performance.now(); // ... const elapsed = performance.now() - start; ``` 2. `requestAnimationFrame()` runs the callback before every frame, roughly 60 times a second, which is ideal for smooth animation. 3. `setTimeout` **with drift compensation**, that is, with the delay corrected each time: ```javascript const start = Date.now(); let count = 0; function tick() { count++; const expected = start + count * 1000; const drift = Date.now() - expected; console.log(`tick ${count}, drift: ${drift}ms`); setTimeout(tick, 1000 - drift); } tick(); ``` This approach accounts for the lateness and keeps the intervals even. ### Summary | Question | Answer | | --- | --- | | Can you guarantee a timer's exact time? | No | | Why? | Single threaded JavaScript, the Event Loop, minimum delays and load | | What really happens? | The timer is added to the task queue and runs later | | Is there an alternative for precision? | Yes: `requestAnimationFrame`, `performance.now`, drift compensation | ### Common mistakes - **Treating the delay as a schedule.** `delay` is a lower bound, not the moment of execution. - **Building a clock on `setInterval`.** Over an hour such a counter drifts noticeably; base it on real time from `Date.now()` or `performance.now()` and redraw the value instead. - **Measuring durations with `Date.now()`.** System time can jump, for example during a clock sync; `performance.now()` is monotonic and more reliable for measurement. - **Forgetting background tabs.** Logic that relies on an even timer tick breaks as soon as the user switches tabs. - **Animating with `setInterval`.** Frame based animation belongs to `requestAnimationFrame`, which is synchronised with screen refresh and avoids tearing.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.