如何在清单 v3 Chrome 扩展中定期调用函数?

How do I call a function periodically in a manifest v3 Chrome extension?

Service workers replace background pages in manifest v3 chrome extensions, and I'm trying to use one for my extension. I need to be able to run a function periodically, and it looks like alarms are the way to go。在示例中,他们建议在服务工作者的顶层执行此操作:

chrome.alarms.create({ delayInMinutes: 3.0 });

chrome.alarms.onAlarm.addListener(() => {
  chrome.action.setIcon({
    path: getRandomIconPath(),
  });
});

不过据我了解,我的服务人员是否在事件之间被杀是不确定的。我相信如果浏览器杀死我的服务工作者,这将每 3 分钟调用一次,因为当脚本重新启动以处理警报时,它将再次 运行 第一行并排队另一个警报。

相比之下,如果浏览器让我的服务工作者在警报之间存活 3 分钟,这将不会循环,因为它只会调用 addListener() 一次,但会调用回调两次(一次用于最初产生此服务工作者的第一个警报,并再次针对在服务工作者调用的第一行注册的警报)。然后 service worker 最终会死去,再也没有警报会唤醒它。

我是不是误解了事件在这里的运作方式?如果没有,我如何注册一次重复发生的警报 chrome.alarms.create({ periodInMinutes: 3.0 }); 并避免每次重新启动我的 service worker 时都重新注册?

注意:delayInMinutes 触发一次,periodInMinutes 重新发生。

虽然它是不确定的,但规则非常简单,并且 worker 的行为几乎与 ManifestV2 的旧事件页面完全一样,主要要点是:

  • 它在注册的 API 事件发生时唤醒
  • 它运行整个脚本,因此 API 侦听器被重新注册
  • 它为唤醒它的 API 事件运行侦听器
  • 它在最后一个 API 事件后 30 秒(MV2 中为 15 秒)后卸载;如果另一个 API 事件被触发,卸载计时器将重新启动;如果有一个开放端口用于 chrome.runtime 消息传递,计时器将延长五分钟,在 MV3 中,消息传递端口在五分钟后强制断开连接,而在 MV2 中,这些端口从不强制断开连接,因此保留 MV2 事件页面还活着。

现在回到那个演示脚本。你是对的:它依赖于非确定性行为。就像扩展文档中的许多示例一样糟糕。使用 API 参考和 devtools 调试器。

一个更现实的例子是只注册一次警报,例如在 chrome.runtime.onInstalled 事件中,因为警报会被浏览器内部记住。另外,最好给它一个id,这样我们就可以检查它是否存在:

chrome.runtime.onInstalled.addListener(() => {
  chrome.alarms.get('periodic', a => {
    if (!a) chrome.alarms.create('periodic', { periodInMinutes: 3.0 });
  });
});

chrome.alarms.onAlarm.addListener(() => {
  chrome.action.setIcon({
    path: getRandomIconPath(),
  });
});