alarms 定时任务
本教程共 56 篇 · 第 37 篇 · 更新于 2026-08-13 · 约 6 分钟阅读
本节目标:学完你能用
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 决定后续节奏。when 和 delayInMinutes 只能二选一,同时给出会触发告警且不生效。
官方示例在扩展安装时顺手建一个演示闹钟,是个很好的习惯:
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);
});
clear 和 clearAll 都支持回调(或 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、由浏览器内核托管、有分钟级最小间隔。把这套学会,扩展的”后台自动运行”能力就立起来了。