cli*_*ait 4 javascript google-chrome-extension service-worker service-worker-events chrome-extension-manifest-v3
Service Worker 替换了 Manifest v3 Google Chrome 扩展程序中的后台页面,并且我\xe2\x80\x99m 尝试为我的扩展程序使用其中一个。文档说应该避免使用计时器 (setTimeout和setInterval),因为当服务工作人员终止时计时器会被取消(这可能随时发生)。与后台页面不同,Service Worker 不能持久存在,并且始终会被终止。文档建议使用Alarms API。
我需要能够在 Manifest v3 Service Worker 中定期运行某个函数,但警报不适合我的用例,因为它们很慢。允许的最短警报持续时间是 1 分钟,但我想以更短的时间间隔 \xe2\x80\x94a 秒或几秒运行一个函数。
\n我尝试event.waitUntil根据这个 Stack Overflow 答案来保持服务工作者的生命。setIntervalHere\xe2\x80\x99是我尝试通过重复调用来模仿 1 秒的解决方案waitUntil:
var e;\n\nfunction doThisEachSecond(resolver) {\n\n console.log(\'running function\')\n\n // \xe2\x80\xa6 CODE \xe2\x80\xa6\n\n e.waitUntil(new Promise(resolve => setTimeout(() => {doThisEachSecond(resolve);}, 1000)));\n resolver();\n}\n\nself.onactivate = event => {\n\n event.waitUntil(new Promise(resolve => {\n e = event;\n doThisEachSecond(resolve);\n }));\n\n console.log(\'activated\');\n};\nRun Code Online (Sandbox Code Playgroud)\n它有很大的问题:
\n由于event.waitUntil使事件调度程序等待,因此当我的 bootlegsetInterval运行时,这些事件不会触发:
chrome.tabs.onUpdated.addListener(\xe2\x80\xa6);\nchrome.tabs.onReplaced.addListener(\xe2\x80\xa6);\nchrome.runtime.onMessage.addListener(\xe2\x80\xa6);\nRun Code Online (Sandbox Code Playgroud)\n我发现,doThisEverySecond如果服务人员继续运行一段时间(例如几分钟),最终就会停止被调用。发生这种情况时,在周期内排队的事件会waitUntil立即全部触发。
看起来我的方法不是\xe2\x80\x99t 的方法。
\n如何在 Chrome Extension Manifest V3 后台服务工作线程中每秒调用一个函数?
\n小智 8
真的很抱歉,但这不可能。
现在我们已经得到了官方的回应:我没有一个好的解决方案给你,但也许一个 hacky 的解决方案会起作用?
我知道你可以在 chrome 中创建一个命名警报,并调用onAlarm所需的函数。我查看了文档,您可以创建的命名警报的数量似乎没有限制;也许你可以创建 59chrome.alarm个,每个偏移量为 1000ms?
哦等等,你不能setTimeout在 Service Worker 中使用。没关系,我只需强制超时即可设置它。
function asyncDelay(msToDelay) {
return new Promise((success, failure) => {
var completionTime = new Date().getTime() + msToDelay
while (true) {
if (new Date().getTime() >= completionTime){
success()
break
}
}
failure()
})
}
Run Code Online (Sandbox Code Playgroud)
好的,现在我需要设置 60 个计时器,以便它们都每隔 1 秒触发一次。不要忘记tick()在设置时调用您的函数,否则它不会立即开始运行。
async function run() {
for(let i = 0; i < 60; i++) {
tick()
await asyncDelay(1000)
chrome.alarms.create(`recurring-polling-thread-${i}`, { periodInMinutes:1 })
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们只需要在每个闹钟结束时触发滴答声即可。
chrome.alarms.onAlarm.addListener(() => {
tick()
})
Run Code Online (Sandbox Code Playgroud)
以及勾选函数中的某种行为来确认它正在工作......
async function tick() {
console.log(new Date().getTime())
}
Run Code Online (Sandbox Code Playgroud)
田田!现在tick()每 1000 毫秒调用一次!
啊废话。
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
Run Code Online (Sandbox Code Playgroud)
好吧,这确实有效,但有些警报同时响起。查看文档表明不遵守 1 秒的粒度:
为了减少用户机器上的负载,Chrome 将警报限制为最多每 1 分钟一次,但可能会延迟任意时间。也就是说,将delayInMinutes 或periodInMinutes 设置为小于1 将不会被执行,并且会导致警告。when 可以设置为“现在”之后不到 1 分钟而不发出警告,但实际上不会导致警报在至少 1 分钟内触发。
在我的本地测试中,我一直在运行这个 Service Worker,它不会休眠大约 10 分钟,而且它几乎每秒都在滴答作响。它并不完美,但我认为这已经足够成功,可以提交。
代码在这里: https: //github.com/EyeOfMidas/second-tick-extension
| 归档时间: |
|
| 查看次数: |
2208 次 |
| 最近记录: |