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

使用ng2-simple-timer在Angular中实现毫秒级秒表遇问题

解决ng2-simple-timer实现毫秒级秒表的异常数值问题

Hey there! 我之前也踩过类似的坑,其实问题根源不是组件本身的bug,而是JavaScript定时器的精度限制加上错误的时间计算逻辑导致的。

问题原因分析

当你把定时器间隔设为0.001(也就是1毫秒)时,浏览器根本无法保证这么高频的定时器触发——JavaScript的setInterval/setTimeout依赖浏览器的事件循环,最小触发间隔受限于浏览器的渲染帧率(通常是16.67毫秒左右,对应60fps),如果主线程有其他任务在执行,定时器还会被延迟。这种情况下,每次触发的实际间隔都远大于1毫秒,你用固定值累加时间的话,误差会迅速放大,最终就出现了异常数值。

正确的实现思路

放弃“固定间隔累加时间”的方式,改用时间戳差值计算:

  • 记录秒表启动时的系统时间戳(Date.now())
  • 用一个合理的间隔(比如10毫秒,即0.01秒)触发定时器,每次触发时计算当前时间戳与起始时间戳的差值
  • 将差值转换成毫秒级的时分秒格式展示

代码示例

import { Component } from '@angular/core';
import { SimpleTimer } from 'ng2-simple-timer';

@Component({
  selector: 'app-stopwatch',
  template: `<div class="stopwatch">{{ formattedTime }}</div>`
})
export class StopwatchComponent {
  startTime: number;
  formattedTime: string;
  timerId: string;

  constructor(private st: SimpleTimer) {}

  startStopwatch() {
    // 记录起始时间戳
    this.startTime = Date.now();
    // 用10毫秒间隔触发定时器,平衡流畅度与性能
    this.timerId = this.st.newTimer('msTimer', 0.01);
    this.st.subscribe('msTimer', () => this.updateDisplay());
  }

  stopStopwatch() {
    this.st.unsubscribe('msTimer');
    this.st.delTimer('msTimer');
  }

  updateDisplay() {
    // 计算真实流逝的毫秒数
    const elapsedMs = Date.now() - this.startTime;
    // 转换为时分秒毫秒格式
    const hours = Math.floor(elapsedMs / 3600000);
    const minutes = Math.floor((elapsedMs % 3600000) / 60000);
    const seconds = Math.floor((elapsedMs % 60000) / 1000);
    const milliseconds = elapsedMs % 1000;
    // 格式化字符串,保证毫秒是三位数字
    this.formattedTime = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;
  }
}

方案优势

不管定时器触发是否延迟,我们都是直接基于系统时间计算真实流逝的时间,完全避免了累加带来的误差。同时10毫秒的间隔既可以保证秒表的流畅刷新,又不会给浏览器带来过大的性能压力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:13:17