想测一段代码跑了多久:做了个秒表工具,顺便搞懂计时精度

举报
静水流深-云海 发表于 2026/09/18 09:57:34 2026/09/18
【摘要】 纯前端秒表,支持开始/暂停/计次分段。技术内核是 performance.now() 高精度计时和 laps 分段记录,重点讲为什么不能用 Date.now() 来量短时间间隔。

有回我想看一段脚本到底跑了 800 毫秒还是 1200 毫秒,随手 Date.now() 减了一下,结果两次跑出来差得离谱。后来才知道,Date.now() 精度不够量短间隔,正经该用 performance.now()。干脆写了个网页秒表,既能掐表又能分段计次,顺便把计时这档事弄明白。

一、为什么不用 Date.now()

Date.now() 返回的是"墙上时钟"时间,精度通常只到毫秒级,而且系统时间一旦被校时(NTP 同步)就会跳变。量长时间段还行,量几百毫秒内的短间隔,误差能到几十毫秒。

performance.now() 不一样:它从页面加载那一刻开始计时,精度到亚毫秒(小数位都有),而且不受系统时间调整影响——校时不会让它跳。测代码耗时、做动画、掐秒表,全该用它。

let start = 0, elapsed = 0, running = false;
function now() { return performance.now(); }   // 高精度,单调不减

function startBtn() {
  if (running) return;
  start = now();
  running = true;
  requestAnimationFrame(loop);
}

二、暂停后怎么接着算

秒表要能暂停再续。关键点是:暂停时把已跑的时间存下来,再开始时只记新起点,而不是从零开始。

function pauseBtn() {
  if (!running) return;
  elapsed += now() - start;   // 把这一段跑了的存起来
  running = false;
}

function resumeBtn() {
  if (running) return;
  start = now();              // 新起点,elapsed 不动
  running = true;
  requestAnimationFrame(loop);
}

function loop() {
  if (!running) return;
  const total = elapsed + (now() - start);
  display(total);
  requestAnimationFrame(loop);
}

注意 loop 里显示的是 elapsed + (now() - start)——已存的时间加上当前这段。这样暂停了多少次都不会错。

三、计次分段(laps)

比赛中常要记"每一圈用了多久"。每点一次"计次",就记一个当前总时长。

let laps = [];
function lapBtn() {
  const total = elapsed + (running ? now() - start : 0);
  const prev = laps.length ? laps[laps.length - 1].total : 0;
  laps.push({ total, split: total - prev });   // split 是这一段增量
  renderLaps(laps);
}

split 是相邻两次计次的差,显示"这一圈比上一圈多用了多少"。

image.png

四、几个细节

点 说明
显示格式 total 毫秒转成 分:秒.毫秒,Math.floor(total/60000) 取分
重置 elapsed=0; laps=[]; running=false
后台节流 requestAnimationFrame 后台会停,但用的是 now()-start 差值,回来自动补正
长任务 跑几小时也没问题,performance.now() 上限够大

小结

秒表的核心不是 setInterval,是 performance.now()——它精度高、单调、不受校时影响,量短间隔比 Date.now() 靠谱得多。暂停靠"存已跑时间 + 记新起点"实现续跑,计次靠存每次总时长再算相邻差。后台节流不影响结果,因为显示永远基于时间差值而非累加。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。