![](/img/trans.png)
[英]How do I call a function periodically in a manifest v3 Chrome extension?
[英]How do you call a function every second in a Chrome Extension Manifest V3 Background Service Worker?
Service Workers 替换了 Manifest v3 Google Chrome Extensions 中的背景页面,我正在尝试将一个用于我的扩展。 文档说应该避免使用计时器( setTimeout
和setInterval
),因为当服务人员终止时计时器会被取消(这可能随时发生)。 与后台页面不同,service workers 不能持久化,并且总是会被终止。 该文档建议改用警报 API 。
我需要能够在 Manifest v3 service worker 中定期运行 function,但警报不适合我的用例,因为它们很慢。 允许的最短警报持续时间是 1 分钟,但我想以更短的间隔运行 function——一秒或几秒。
根据这个 Stack Overflow 答案,我尝试使用event.waitUntil
让服务工作者保持活动状态。 这是我尝试通过重复waitUntil
调用模仿 1 秒setInterval
的解决方案:
var e;
function doThisEachSecond(resolver) {
console.log('running function')
// … CODE …
e.waitUntil(new Promise(resolve => setTimeout(() => {doThisEachSecond(resolve);}, 1000)));
resolver();
}
self.onactivate = event => {
event.waitUntil(new Promise(resolve => {
e = event;
doThisEachSecond(resolve);
}));
console.log('activated');
};
它有很大的问题:
由于event.waitUntil
使事件调度程序等待,因此当我的盗版setInterval
运行时,这些事件不会触发:
chrome.tabs.onUpdated.addListener(…);
chrome.tabs.onReplaced.addListener(…);
chrome.runtime.onMessage.addListener(…);
而且我发现如果 service worker 运行一段时间(比如几分钟), doThisEverySecond
最终会停止被调用。 发生这种情况时,在waitUntil
期间排队的事件会立即全部触发。
看来我的方法不是通往 go 的方法。
您如何在 Chrome Extension Manifest V3 Background Service Worker 中每秒调用 function?
真的很抱歉,但这是不可能的。
既然我们已经得到了官方的回应:我没有适合你的好解决方案,但也许一个 hacky 的解决方案会奏效?
我知道您可以在 chrome 中创建一个命名警报,并让onAlarm
调用所需的 function。我查看了文档,您可以创建的命名警报的数量似乎没有限制; 也许您可以创建 59 个chrome.alarm
,每个偏移量为 1000 毫秒?
哦等等,你不能在 service worker 中使用setTimeout
。 没关系,我会强制超时来设置它。
function asyncDelay(msToDelay) {
return new Promise((success, failure) => {
var completionTime = new Date().getTime() + msToDelay
while (true) {
if (new Date().getTime() >= completionTime){
success()
break
}
}
failure()
})
}
好的,所以现在我需要设置 60 个定时器,这样它们都会依次触发 1 秒。 不要忘记在设置时调用您的tick()
function,否则它不会立即开始运行。
async function run() {
for(let i = 0; i < 60; i++) {
tick()
await asyncDelay(1000)
chrome.alarms.create(`recurring-polling-thread-${i}`, { periodInMinutes:1 })
}
}
然后我们只需要在每次闹钟结束时触发滴答声。
chrome.alarms.onAlarm.addListener(() => {
tick()
})
勾选 function 中的某种行为以确认它正在工作......
async function tick() {
console.log(new Date().getTime())
}
多田! 现在每 1000 毫秒调用一次tick()
!
啊废话。
background.js:1 1647382803613
background.js:1 1647382804613
background.js:1 1647382805613
(8) background.js:1 1647382806614
(13) background.js:1 1647382806615
background.js:1 1647382807617
background.js:1 1647382808627
background.js:1 1647382809642
好吧,它有点管用,但一些警报同时响起。 查看 文档表明不遵守 1 秒的粒度:
为了减少用户机器上的负载,Chrome 将警报限制为最多每 1 分钟一次,但可能会延迟任意多的时间。 也就是说,将 delayInMinutes 或 periodInMinutes 设置为小于 1 将不会被接受并会引起警告。 when 可以设置为在“现在”之后不到 1 分钟而不发出警告,但实际上不会导致至少 1 分钟的警报触发。
在我的本地测试中,我一直在运行这个 service worker 大约 10 分钟,它不会休眠,而且它几乎每秒都在滴答作响。 它并不完美,但我认为这足以提交。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.