首页 / 浏览器扩展开发入门教程 / alarms 定时任务

浏览器扩展开发入门教程

alarms 定时任务

本教程共 56 篇 · 第 37 篇 · 更新于 2026-08-13 · 约 6 分钟阅读

alarms定时任务chrome.alarms.createonAlarm后台定时MV3

本节目标:学完你能用 chrome.alarms 在扩展里设置周期或延时任务,并在服务工作者休眠后依然准时被唤醒。

“每隔几分钟检查一次更新""每天定时清理缓存”,这类需求在扩展里很常见。在 MV3 之前,很多人用 setInterval 在后台死循环。但 MV3 的后台是服务工作者,它随时会休眠,普通的 setInterval 一睡就停,完全靠不住。chrome.alarms 正是为此设计的——它由浏览器内核保管,到点了才把你的服务工作者叫醒。

37-1 为什么不用 setInterval

先说清楚问题根源。MV3 的服务工作者是事件驱动的,平时不占资源、不常驻内存,空闲一会儿就被系统回收。你在里面写 setInterval(fn, 60000),第一次可能跑,但服务工作者一旦休眠,定时器随之失效,再也不会触发。等用户下次碰巧唤醒扩展,定时器才”重生”,但中间那段间隔全丢了。

chrome.alarms 不一样:闹钟的计时由浏览器进程负责,不依赖你的服务工作者是否活着。到点时,Chrome 主动唤醒服务工作者并触发 onAlarm 事件。这才是 MV3 下可靠的定时方案。

Note

一句话记忆:setInterval 活在服务工作者的内存里(会睡死),alarms 活在浏览器内核里(准时唤醒)。做后台周期任务,只用 alarms

37-2 创建定时任务:create

create 用来登记一个闹钟。第一个参数是名字(可省略,省略就是默认闹钟),第二个是闹钟配置。

// 1 分钟后触发一次
chrome.alarms.create("check-update", { delayInMinutes: 1 });

// 1 分钟后首次触发,之后每 2 分钟重复一次
chrome.alarms.create("sync-data", {
  delayInMinutes: 1,
  periodInMinutes: 2
});

// 指定绝对时间点触发(毫秒时间戳)
chrome.alarms.create("at-noon", { when: Date.now() + 60 * 60 * 1000 });

配置对象 alarmInfo 有三个关键字段:

  • when:一个绝对时间,用 Date.now() + 偏移 算出毫秒时间戳,到点就响。
  • delayInMinutes:相对”现在”延迟多少分钟后首次触发。
  • periodInMinutes:触发后每隔多少分钟再触发,写上它就变成周期闹钟。

这三个字段可以组合:delayInMinutes 决定首次,periodInMinutes 决定后续节奏。whendelayInMinutes 只能二选一,同时给出会触发告警且不生效。

官方示例在扩展安装时顺手建一个演示闹钟,是个很好的习惯:

chrome.runtime.onInstalled.addListener(({ reason }) => {
  if (reason !== chrome.runtime.OnInstalledReason.INSTALL) return;
  chrome.alarms.create("demo-default-alarm", {
    delayInMinutes: 1,
    periodInMinutes: 1
  });
});

37-3 监听触发:onAlarm

闹钟响了,靠 onAlarm 接住。回调拿到一个 alarm 对象,里面有名字、计划触发时间等信息。

chrome.alarms.onAlarm.addListener((alarm) => {
  console.log("闹钟响了:", alarm.name);
  // 在这里做你的定时工作,比如拉取更新
  doPeriodicWork();
});

alarm 对象包含 name(你创建时起的名字)、scheduledTime(计划触发的时间戳)、periodInMinutes(周期,非周期闹钟为 undefined)。你可以用 alarm.name 区分多个闹钟,分别走不同逻辑:

chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === "check-update") {
    checkForUpdates();
  } else if (alarm.name === "sync-data") {
    syncUserData();
  }
});
Tip

因为 onAlarm 会唤醒服务工作者,所以你的定时逻辑直接写在这个监听器里即可,不必另起 setInterval。监听器本身是轻量的事件注册。

37-4 取消与查询:clear / getAll

闹钟用完了,或者用户关掉了某个功能,记得清掉,别让它一直空转耗电。

// 取消指定名字的闹钟
chrome.alarms.clear("check-update", (wasCleared) => {
  console.log("是否成功取消:", wasCleared);
});

// 取消所有闹钟
chrome.alarms.clearAll((wasCleared) => {
  console.log("全部清空:", wasCleared);
});

clearclearAll 都支持回调(或 await 拿布尔结果),返回 true 表示确实有这么个闹钟被取消了。想看看当前还挂着哪些闹钟,用 getAll

const alarms = await chrome.alarms.getAll();
alarms.forEach((a) => console.log(a.name, a.periodInMinutes));

官方示例的”取消全部”封装就很典型:

async function cancelAllAlarms() {
  return chrome.alarms.clearAll((wasCleared) => {
    if (wasCleared) console.log("已取消全部闹钟");
  });
}

37-5 最小间隔与精度

闹钟不是毫秒级定时器,它有粒度和精度上的限制,写之前心里要有数。

第一,周期闹钟有最小间隔。Chrome 120 起,闹钟至少每 30 秒触发一次——periodInMinutes / delayInMinutes 最小取 0.5(0.5 分钟就是 30 秒);小于 0.5 的值不会被采纳,而且会触发告警。如果你需要”每秒一次”的密集轮询,alarms 不合适,应该重新设计功能。

第二,触发时间不是绝对精确。浏览器为了省电,可能把多个闹钟合并、或稍微推迟,所以别拿它做对时间精度要求极高的活儿(比如计时器界面)。

第三,闹钟受用户机器状态影响。设备休眠期间闹钟不会响,但计时照常进行,唤醒后错过的闹钟会补触发(重复闹钟至多补一次);浏览器完全关闭期间则不会触发。

Warning

periodInMinutes 设得过小(比如想实现秒级轮询)不仅不推荐,还可能在审核或实际运行中被浏览器限制。周期任务,老老实实用”分钟”为单位去设计。

37-6 典型用法

把整章串起来,一个”每 5 分钟检查一下远程配置、有变化就提示”的最小骨架是这样的:

{
  "name": "Alarms API Demo",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": ["alarms"],
  "background": { "service_worker": "background.js" }
}
// background.js
chrome.runtime.onInstalled.addListener(() => {
  chrome.alarms.create("poll-config", {
    delayInMinutes: 1,
    periodInMinutes: 5
  });
});

chrome.alarms.onAlarm.addListener(async (alarm) => {
  if (alarm.name !== "poll-config") return;
  const res = await fetch("https://example.com/config.json");
  const cfg = await res.json();
  // 用 storage 记住上次的配置,对比是否有变化
  const old = await chrome.storage.local.get("config");
  if (JSON.stringify(old.config) !== JSON.stringify(cfg)) {
    await chrome.storage.local.set({ config: cfg });
    console.log("配置有更新");
  }
});

这个例子把 alarms(定时唤醒)、storage(跨组件存状态)、fetch(拉数据)串成了一条完整的后台定时链路,也是 MV3 下做”轻量周期任务”的标准姿势。

37-7 清理与生命周期

闹钟是”登记一次、反复生效”的,所以生命周期管理要上心。最常见的两个场景:功能被用户关闭时清掉对应闹钟;扩展更新时避免重复登记。

避免重复登记很简单:在 onInstalled 里,只对”首次安装”建闹钟,更新时跳过。前面示例已经用了 reason !== INSTALL 这个判断,就是这个意思。如果你每次启动都无条件 create 同名闹钟,Chrome 会把它当作”重置”,虽不至于出错,但语义上不干净。

功能开关也要联动:用户关掉”自动同步”后,记得 clear 掉那个同步闹钟;重新打开时再 create。否则闹钟会一直在后台空跑,白耗资源、也可能触发不必要的网络请求。

// 用户关闭功能时
await chrome.alarms.clear("sync-data");

// 用户重新开启时
await chrome.alarms.create("sync-data", {
  delayInMinutes: 1,
  periodInMinutes: 5
});

把这些关系理清楚,你的定时任务就不会”关不掉、重复建、乱触发”。

Note

本章要点:用 create 登记(when/delayInMinutes/periodInMinutes),用 onAlarm 接活,用 clear/clearAll/getAll 管理,牢记它替代的是 setInterval、由浏览器内核托管、有分钟级最小间隔。把这套学会,扩展的”后台自动运行”能力就立起来了。