当前位置: 首页 > news >正文

【JavaScript】实现一个高精度的定时器

JS 自带的 setTimeout / setInterval 定时器精度有限,常常出现 延迟漂移(drift),尤其在页面被挂起、CPU 忙碌时。


❌ 为什么默认定时器不精确?

  • 事件循环setTimeout(fn, delay) 的回调要等 主线程空闲 才能执行,可能被阻塞。
  • 嵌套定时器最小延迟:Chrome、Firefox 等浏览器在后台或非激活标签页中,setTimeout 最小延迟可能变为 1000ms。
  • 累积误差setInterval 是按照“上一次回调开始”计算的,而不是“理想时间点”。执行时间一长,误差会 逐渐累积

✅ 高精度定时器实现思路

🔹 普通 setInterval 的问题

setInterval(() => {console.log(performance.now());
}, 100);

问题在于:

  1. JS 是单线程,假设回调耗时 20ms,那么下一个 100ms 的周期会推迟 20ms。
  2. 误差会 累积:100 → 120 → 140 → …,时间漂移越来越严重。

核心思路:

  1. performance.now()(微秒级,远比 Date.now() 好)。
  2. 不依赖 setInterval,而是递归使用 setTimeoutrequestAnimationFrame
  3. 每次 tick 都以「理想时钟」为基准,而不是以上次实际执行时间为准。这样就算某一次任务被阻塞了(比如长任务或 GC),也能 自我修正,误差不会累积。
  4. 通过“理想执行时间”与“实际执行时间”的差值来做 纠偏(drift correction)
  5. 👉 本质:将 interval 看成理想时钟,而不是依赖 JS 事件循环。

📌 示例:高精度定时器(纠偏版)

function highPrecisionTimer(callback, interval) {let expected = performance.now() + interval;let timerId;function step() {const drift = performance.now() - expected; // 实际时间 - 理想时间callback();// 更新理想的下一次触发点expected += interval;// 纠正漂移:如果 drift > interval,说明任务卡了,就补偿timerId = setTimeout(step, Math.max(0, interval - drift));}timerId = setTimeout(step, interval);return () => clearTimeout(timerId); // 返回清除函数
}// 使用:每 100ms 执行一次
const stop = highPrecisionTimer(() => {console.log("tick", performance.now());
}, 100);// 5 秒后停止
setTimeout(stop, 5000);

👉 特点:

  • 误差不会无限累积(比 setInterval 精准得多)。
  • 即使执行耗时,也会自动调整到理想时钟。

📌 示例:用 requestAnimationFrame 实现(适合动画)

requestAnimationFrame(callback) 会在 下一帧渲染前 执行,浏览器大多数显示器刷新率是 60Hz(大约 16.6ms 一帧)。

所以:

function loop(now) {console.log(now); // rAF 自带高精度时间戳requestAnimationFrame(loop);
}
requestAnimationFrame(loop);

输出时间间隔大约是 16.6ms,和屏幕刷新强绑定。

function highPrecisionRAF(callback, interval) {let start = performance.now();let lastTime = start;function loop(now) {if (now - lastTime >= interval) {lastTime += interval;callback();}requestAnimationFrame(loop);}requestAnimationFrame(loop);
}// 使用:每 100ms 执行一次
highPrecisionRAF(() => {console.log("tick", performance.now());
}, 100);

👉 特点:

  • 绑定浏览器渲染帧(大约 16.6ms 一次)。
  • 更适合动画相关的定时器(不会掉帧)。
  • 内置高精度 DOMHighResTimeStamp(和 performance.now() 一样)。和屏幕刷新率同步(比如 60Hz),避免动画卡顿。
  • 👉 本质:把任务挂载在浏览器渲染周期上,获得更平滑的定时效果。

📌 Node.js 环境高精度定时器

Node.js 可以用 setTimeout + process.hrtime.bigint()(纳秒级),同样做 drift correction。


✅ 总结

  • setInterval:误差会累积,不推荐。
  • setTimeout + 纠偏:高精度,适合定时任务。
  • requestAnimationFrame:渲染友好,适合动画。
  • Web Worker + setTimeout:适合后台计算,避免主线程阻塞。

要不要我给你写一个 支持暂停 / 恢复 / 停止 的高精度定时器类?这样能直接用在项目里,管理定时任务更方便。


文章转载自:

http://tEA67hP1.hthmx.cn
http://WAN4rNtn.hthmx.cn
http://WmmfBwTX.hthmx.cn
http://v02FWBsg.hthmx.cn
http://8CDMRJFk.hthmx.cn
http://r86BUBNU.hthmx.cn
http://bDvek6Pm.hthmx.cn
http://PxYDl7w6.hthmx.cn
http://eqy9NmKv.hthmx.cn
http://nzZaxROd.hthmx.cn
http://43CxodHm.hthmx.cn
http://31hJB6rM.hthmx.cn
http://p7HtoCwJ.hthmx.cn
http://gh7wheR8.hthmx.cn
http://gqlumjd0.hthmx.cn
http://hL1aVVHL.hthmx.cn
http://HenQVC46.hthmx.cn
http://k0wj1P7K.hthmx.cn
http://8cHn48Jf.hthmx.cn
http://S2O0pzG2.hthmx.cn
http://7DLk4Mul.hthmx.cn
http://SbKKaT7I.hthmx.cn
http://C6QkvgsF.hthmx.cn
http://6HmgQt9o.hthmx.cn
http://ub36c5yw.hthmx.cn
http://PUeIlAjT.hthmx.cn
http://SpoGRDUB.hthmx.cn
http://bDavyM1t.hthmx.cn
http://FMee4f4L.hthmx.cn
http://I6ROlOAF.hthmx.cn
http://www.dtcms.com/a/384915.html

相关文章:

  • 无偏估计-
  • SQL-流程控制函数
  • TNNLS-2015《Linear-Time Subspace Clustering via Bipartite Graph Modeling》
  • 线性代数 · 行列式 | 子式 / 主子式 / 顺序主子式 / 余子式 / 代数余子式
  • LLM的MTP论文阅读
  • 软考-系统架构设计师 软件工程详细讲解
  • MATLAB 实现基于 GMM-HMM的语音识别系统
  • Day24_【深度学习(4)—PyTorch使用—张量的数值计算】
  • 2019年下半年 系统架构设计师 综合知识
  • C++类和对象详解(2);初识类的默认成员函数
  • AI智能体的应用前景
  • 文档驱动的AI协作 (DDAC) 工作流
  • Selenium 与 Playwright 安装及浏览器驱动配置
  • 数字丝绸之路的暗礁,解码“一带一路”与RCEP时代的跨境法治挑战
  • fabric启动节点var/hyperledger/production: permission denied
  • 小型无人机传感器仿真模型MATLAB实现方案
  • 拓扑dp|博弈|正难则反
  • linux时间管理
  • 第2章 语言模型:自然语言处理的基石
  • 汽车电子电气架构 --- 新趋势下的挑战与技术
  • 地铁站电子钟:NTP实时校准时间
  • 【数据集】2025年国家自然科学基金立项名单(经管类)
  • Elastic APM 2025 新特性:Tail-based Sampling 和 GenAI 优化
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘sklearn’ 问题
  • 《二战系统分析师》第五章总结
  • 机器学习中的距离总结
  • MongoDB集群开发完全指南:从原理到实践
  • apache phoenix sql 命令大全详解
  • python 读取大文件优化示例
  • 布草洗涤厂设备租赁押金原路退回系统—东方仙盟