浏览器倒计时怎样避免越走越慢:从结束时间到刷新恢复

举报
yd_210400787 发表于 2026/10/22 11:31:53 2026/10/22
【摘要】 以一个无外部依赖的专注时钟为例,介绍绝对结束时间、暂停与继续、本地保存和刷新恢复,并用浏览器可控时钟核验8项行为边界。

做一个25分钟专注计时器,最容易写出的版本是每秒把数字减一。前台页面里看起来正常,切换标签页、暂停再继续、刷新页面之后,问题才逐渐暴露。

本文用新做的“节奏·专注时钟”说明另一种实现:保存结束时间,定时器只负责更新画面。这个单文件页面支持25分钟专注、5分钟短休息和15分钟长休息,无需后端或第三方依赖。

一、回调次数不等于经过时间

setInterval 表示安排回调,不保证每次都准时执行。页面切到后台、主线程忙于其他任务时,渲染更新可能变慢。如果每次回调只减一秒,显示时间就会落后于实际经过时间。

这次实现不累计回调次数,而是在开始时记录结束时间:

state.deadline = Date.now() + state.remaining;
state.running = true;

每次绘制重新计算剩余毫秒数:

const left = () => state.running
  ? Math.max(0, state.deadline - Date.now())
  : state.remaining;

即使两次绘制间隔突然变长,下次回调仍然依据当前时间计算结果。实现中每250毫秒刷新一次画面,显示秒数向上取整,避免还剩不足一秒时提前显示零。

这种方案依赖系统时钟。用户手动调整时间或系统发生校时,会影响倒计时结果。它适合日常专注工具,不能直接当作计费或考试的可信计时依据。

二、暂停保存时长,继续重建结束时间

运行状态保存 deadline;暂停状态保存 remaining。暂停先读取当前剩余时长,再清除结束时间:

state.remaining = left();
state.running = false;
state.deadline = null;

继续时用“当前时间加剩余时长”建立新的结束时间。这样暂停期间不会消耗本轮时间。

切换模式则重置全部计时状态,避免上一种模式的结束时间继续作用于下一种模式。重置按钮同样停止计时,恢复当前模式的完整时长。

三、刷新恢复必须验证存储数据

页面将模式、剩余时间、运行状态、结束时间和完成标记保存到 localStorage。初始化时先检查模式是否存在、数字是否有限且处于合理范围、状态字段是否为布尔值,再采用恢复数据。

运行中刷新,保留原来的结束时间;暂停后刷新,保留暂停的剩余时长。重新打开时如果结束时间已经过去,显示“本轮已完成”,而不是把负数显示出来或自动开始下一轮。

本地存储可能不可用,读取和写入都包在 try/catch 中。此时计时器仍可在当前页面工作,只是不再承诺刷新恢复。页面也明确说明数据保存在当前浏览器,关闭网页后不会发出提醒。

四、用可控时间核验边界

本次使用浏览器自动化的时钟控制核验了以下行为,而不是实际等待25分钟:

场景 观察结果
初始状态 25:00
开始后推进61秒 23:59
暂停后再推进90秒 仍为23:59
暂停状态刷新 保留23:59并显示已暂停
继续并推进剩余时间 00:00,本轮已完成
切换短休息 05:00
休息运行30秒后刷新 保留04:30
点击重新计时 恢复05:00并停止运行

页面还为开始、暂停、完成状态提供文字反馈。空格键可开始或暂停;按钮获得焦点时保留浏览器原生键盘行为,避免一次按键触发两次切换。

五、部署时再核对一次正文

单文件静态页面可以直接用Nginx托管。将文件放到专用目录,配置监听端口后先执行 nginx -t,再重新加载服务,随后检查访问响应。

这次部署除了确认HTTP 200,还对比了公网返回正文与本地HTML的SHA-256,结果一致。这个检查能发现“端口通了,却还在展示默认欢迎页”等问题。配置重新加载后应再次请求页面,避免把重新加载前的一次响应误当作最终结果。

一个小计时器不需要复杂框架,但需要明确区分时间来源、运行状态、保存内容和恢复规则。把这些边界写清楚,暂停、后台切换和刷新就能采用同一套规则处理。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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