JavaScript定时器异步执行,回调时机由事件循环决定;setTimeout(0)不立即执行,需等同步代码和微任务完成;setInterval易导致任务堆积,推荐递归setTimeout;可用Promise封装实现await等待;务必及时清除定时器防止内存泄漏。

JavaScript 定时器本身是异步的,不会打断同步代码执行,但能精准控制回调触发的时机。关键不在“它什么时候开始计时”,而在于“它什么时候真正被执行”——这由事件循环决定,而非你写的 delay 数值。
定时器的执行时机由事件循环决定
即使写 setTimeout(fn, 0),回调也不会立刻运行。浏览器会把回调放进宏任务队列,等当前调用栈清空、所有微任务(如 Promise.then)执行完后,才轮到它。
- 同步代码优先执行,不管定时器 delay 多小
- 多个
setTimeout按注册顺序排队,但实际执行时间受主线程负载影响 -
setInterval不保证严格周期:若回调执行耗时 > 间隔,下一次会紧接上一次结束才启动,不会堆积
避免 setInterval 的累积风险
重复任务用 setInterval 容易出问题:比如网络请求未返回就再次触发,导致并发失控或状态错乱。
- 推荐用
setTimeout递归调用替代:每次回调完成后再设下一次定时 - 这样可确保前一次逻辑彻底结束,再启动下一轮,节奏可控
- 示例:
function tick() { /* 执行任务 */ setTimeout(tick, 2000); }
让定时逻辑按需同步化
如果需要“等定时器完成再继续”,不能靠写顺序,得用 Promise 封装:
立即学习“Java免费学习笔记(深入)”;
- 把
setTimeout包进 Promise,配合async/await实现线性流程 - 例如:
const delay = ms => new Promise(r => setTimeout(r, ms)); - 之后可写
await delay(1500); console.log('等完再执行');
清除定时器是必要习惯
没被清理的定时器会持续占用内存,尤其在组件卸载、页面跳转时容易引发错误回调。
- 保存
setTimeout或setInterval返回的 ID - 在不再需要时主动调用
clearTimeout(id)或clearInterval(id) - React 中常在
useEffect清理函数里做这件事;原生 JS 则在 DOM 移除或状态变更时处理


















