setTimeout 不准确的原因和解决办法:
-
事件循环延迟:JavaScript 是单线程的,如果事件循环中有其他任务阻塞了执行,
setTimeout
的回调可能会延迟执行。前一个任务耗时过长,定时器不是立刻放入事件队列中的,而是同步任务执行完了之后,timer 模块计算时间到了,再放入队列中,参考- 解决方法:确保
setTimeout
的回调函数尽量简短,避免长时间的计算或者阻塞操作。
- 解决方法:确保
-
浏览器最小时间间隔:大多数浏览器的
setTimeout
最小时间间隔为 4 毫秒。- 解决方法:如果需要更精确的定时器,可以使用
requestAnimationFrame
,但它的用途通常不同于setTimeout
。
- 解决方法:如果需要更精确的定时器,可以使用
setInterval 不准确的原因和解决办法:
-
累积误差:
setInterval
的执行时间会受到前一个回调函数执行时间的影响,导致累积误差;即定时器回调函数耗时过长,累积误差通常会导致下一个回调函数的执行比预期的要晚。但是就时间间隔来看还是很均匀的。- 解决方法:【如过你想让执行的时间是绝对时间】在每次回调中计算下一次的执行时间,而不是依赖于固定的时间间隔。这样可以避免累积误差。这个就是使用 setTimeout 模拟 setInterval
- 常见情况:在 ajax 请求的时候使用 setInterval,网络慢的时候一个请求很长时间才返回,所以会出现连续发好几个请求的现象。可以使用这篇文章的第二种方法代替。
-
事件循环延迟:前一个任务耗时过长,与
setTimeout
类似,setInterval
也可能受到事件循环的延迟影响。【时间间隔会变短!越来越快】- 解决方法:【如果场你想保证运行的时间间隔】,那就是setTimeout 模拟 setInterval,setTimeout回调执行之后再调用setTimeout
-
页面不可见时的停止:在页面不可见时,浏览器可能会降低或停止
setInterval
的执行,以节省资源。- 解决方法:如果需要在页面不可见时继续执行任务,可以考虑使用
requestAnimationFrame
或Web Workers
。
- 解决方法:如果需要在页面不可见时继续执行任务,可以考虑使用
-
跨浏览器兼容性问题:不同浏览器可能对
setInterval
的实现方式和准确性有所差异。- 解决方法:测试并针对不同浏览器进行调整,或者选择使用第三方库来处理定时器。
总的来说,为了确保定时器的准确性,尽量保持回调函数的执行时间短暂,并且在需要更高精度的情况下考虑使用其他 API,例如 requestAnimationFrame
或 Web Workers
。