如何在清单 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(),
});
});
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(),
});
});