You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript实现精准毫秒秒级计时 解决setTimeout计时偏差问题

问题原因分析
  • 原setTimeout版本是固定步进逻辑:每次执行固定将计时值+10ms(你代码中自定义的millisecond变量每加1对应10ms,满100进1秒),所以可以输出连续的两位毫秒序列,但是setTimeout本身受事件循环阻塞,长期运行会出现累计偏差。
  • 改用Date.now()后的版本存在两个核心问题:
    1. 用requestAnimationFrame调度渲染,帧率约60fps,每次调用间隔约16ms,远大于你需要的10ms步长,自然会跳过毫秒值
    2. 直接从Date.now()取时间快照,没有模拟步进逻辑,只会输出当前真实时间对应的毫秒值,不会补全中间跳过的序列
解决方法

核心思路是:用Date.now()计算真实累计时长作为基准,按照你需要的10ms步长模拟生成连续的时间序列,同时动态调整setTimeout调度间隔,避免累计漂移

修改后可直接运行的代码如下:

// 步长配置,10对应原逻辑的10ms步进,要1ms级输出就改为1
const STEP = 10;
var paused = true,
    lastTickTime = 0, // 上次执行步进的真实时间戳
    currentCount = 0; // 累计步进次数,单位和STEP对应

// 原格式化逻辑保留
function format(n) {
  return (n < 10 ? "0" + n : n);
}

function render() {
  // 从累计步进值计算完整时间
  const totalMs = currentCount * STEP;
  const hour = format(Math.floor(totalMs / 3600000));
  const min = format(Math.floor((totalMs % 3600000) / 60000));
  const sec = format(Math.floor((totalMs % 60000) / 1000));
  const ms = format(Math.floor((totalMs % 1000) / 10));
  // 这里替换为你自己的输出逻辑,比如更新DOM或者打印
  console.log(`${hour}:${min}:${sec}.${ms}`);
}

function runTick() {
  if (paused) return;
  const now = Date.now();
  // 计算上次执行到现在需要补的步数,避免跳号
  const delta = now - lastTickTime;
  const steps = Math.floor(delta / STEP);
  if (steps > 0) {
    currentCount += steps;
    // 对齐步长时间,消除误差
    lastTickTime = now - (delta % STEP);
    render();
  }
  // 动态计算下一次调度的间隔,保证刚好在步长点触发
  const nextDelay = STEP - (Date.now() - lastTickTime);
  setTimeout(runTick, nextDelay);
}

function startStopwatch(evt) {
  if (paused) {
    paused = false;
    lastTickTime = Date.now();
    runTick();
  }
}

function stopStopwatch(evt) {
  if (!paused) {
    paused = true;
  }
}

function resetStopwatch(evt) {
  currentCount = 0;
  lastTickTime = Date.now();
  render();
}

该方案既保留了连续的步进输出效果,又用真实时间校准,不会出现传统setTimeout计时的累计偏差问题。

内容的提问来源于stack exchange,提问作者Ruan Matt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:15:00