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

Chrome扩展中chrome.alarms遇系统时间变更异常的修复咨询

问题描述

我正在使用chrome.alarm在Chrome扩展图标上显示倒计时,更新频率约为每秒一次。当前遇到的问题是:

  • 手动调整系统时间向前,或电脑从睡眠状态唤醒时,计数器会开始高频更新(每秒多次)以追赶新的系统时间;
  • 将系统时间向后调整,计时器则会停止运行。

希望修改代码,使计时器在系统时间变更时直接跳转至当前时间,恢复正常的每秒更新节奏。

测试用扩展代码如下:

manifest.json

{
  "manifest_version": 3,
  "name": "Test timer",
  "author": "test",
  "description": "Test chrome.alarm",
  "version": "0.0.1",

  "permissions": [
    "alarms"
  ],
  "action": {},
  "background": {
    "service_worker": "service_worker.js"
  }
}

service_worker.js(原代码)

let i = 0,
    start = new Date().getTime(),
    pad = (n,s=2) => ("0"+n).slice(-s),
    time = d => pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()) + "." + pad(d.getMilliseconds(),3);

chrome.alarms.onAlarm.addListener(loop);

console.log("started");
loop();

function loop()
{
  const now = new Date().getTime(),
        //make sure timer doesn't drift from starting point
        next = now - ((now - start) % 1000);

  //repeat after 1sec
  chrome.alarms.create({ when: next + 1000 });

  chrome.action.setBadgeText({text:"" + (i = ++i % 1000)});
  console.log("Date:", time(new Date(now)), "alarm:", time(new Date(next)));
}
问题根源

原代码依赖固定的初始start时间计算下一次闹钟触发点,当系统时间发生跳变(向前调、向后调、睡眠唤醒)时,now - start的差值不再反映实际流逝的时间:

  • 系统时间向前跳:now - start的差值突然变大,计算出的next会远小于当前now,导致chrome.alarms.create立刻触发闹钟,形成高频更新;
  • 系统时间向后跳:next + 1000会落在当前now的过去,Chrome不会触发过去的闹钟,导致计时器停止。
解决方案

放弃依赖固定初始时间的逻辑,改为基于当前系统时间动态计算下一个整秒触发点,同时加入系统时间跳变的检测:每次触发闹钟时,对比当前时间与预期的触发时间,若差值超过合理阈值(比如1.5秒),判定为系统时间发生变化,直接重置计时逻辑,以当前时间为基准重新计算下一次触发点。

修改后的代码

service_worker.js

let i = 0;
let lastScheduled = null; // 跟踪上一次预期的闹钟触发时间
const pad = (n, s = 2) => ("0" + n).slice(-s);
const time = d => pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()) + "." + pad(d.getMilliseconds(), 3);

chrome.alarms.onAlarm.addListener(loop);

console.log("started");
loop();

function loop() {
  const now = new Date().getTime();
  let nextTrigger;

  // 检测系统时间是否发生跳变
  if (lastScheduled && Math.abs(now - lastScheduled) > 1500) {
    // 时间差超过1.5秒,判定为系统时间变更,重置为当前时间的下一个整秒
    nextTrigger = now - (now % 1000) + 1000;
  } else {
    // 正常情况,计算下一个整秒触发点
    nextTrigger = now - (now % 1000) + 1000;
  }

  // 更新跟踪的预期触发时间
  lastScheduled = nextTrigger;
  // 创建下一次闹钟
  chrome.alarms.create({ when: nextTrigger });

  // 更新徽章计数(模拟倒计时/计数逻辑)
  i = (i + 1) % 1000;
  chrome.action.setBadgeText({ text: "" + i });
  
  console.log("Date:", time(new Date(now)), "Next alarm:", time(new Date(nextTrigger)));
}
代码说明
  1. 移除固定start变量:改用lastScheduled跟踪上一次预期的闹钟触发时间,避免依赖初始时间;
  2. 系统时间跳变检测:通过对比当前时间与lastScheduled的差值,判断是否发生时间跳变,阈值设为1.5秒是为了兼容正常的闹钟触发误差;
  3. 动态计算触发点:无论是否发生时间跳变,都基于当前系统时间计算下一个整秒点,确保计时器始终与当前系统时间同步;
  4. 重置计数逻辑:当检测到时间跳变时,直接以当前时间为基准重新开始,避免高频更新或停止的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 05:37:09