简体   繁体   English

您如何在 Chrome Extension Manifest V3 Background Service Worker 中每秒调用 function?

[英]How do you call a function every second in a Chrome Extension Manifest V3 Background Service Worker?

Service workers replace background pages in Manifest v3 Google Chrome Extensions, and I'm trying to use one for my extension. Service Workers 替换了 Manifest v3 Google Chrome Extensions 中的背景页面,我正在尝试将一个用于我的扩展。 The documentation says timers ( setTimeout and setInterval ) should be avoided because timers get canceled when service workers terminate (which may happen at any time).文档说应该避免使用计时器( setTimeoutsetInterval ),因为当服务人员终止时计时器会被取消(这可能随时发生)。 Unlike background pages, service workers can't be persistent and will always be subject to termination.与后台页面不同,service workers 不能持久化,并且总是会被终止。 The documentation recommends using the Alarms API instead.该文档建议改用警报 API

I need to be able to run a function periodically in a Manifest v3 service worker, but alarms don't suit my use case because they're slow.我需要能够在 Manifest v3 service worker 中定期运行 function,但警报不适合我的用例,因为它们很慢。 The shortest allowed alarm duration is 1 minute, but I want to run a function in shorter intervals—a second or a few seconds.允许的最短警报持续时间是 1 分钟,但我想以更短的间隔运行 function——一秒或几秒。

I tried using event.waitUntil to keep the service worker alive per this Stack Overflow answer.根据这个 Stack Overflow 答案,我尝试使用event.waitUntil让服务工作者保持活动状态。 Here's my attempted solution at mimicking a 1-second setInterval with repeating waitUntil calls:这是我尝试通过重复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');
};

It has big problems:它有很大的问题:

Since event.waitUntil makes the event dispatcher wait, these events don't fire when my bootleg setInterval is running:由于event.waitUntil使事件调度程序等待,因此当我的盗版setInterval运行时,这些事件不会触发:

chrome.tabs.onUpdated.addListener(…);
chrome.tabs.onReplaced.addListener(…);
chrome.runtime.onMessage.addListener(…);

And I found that doThisEverySecond eventually stops getting called if the service worker is left to run for some time like a few minutes.而且我发现如果 service worker 运行一段时间(比如几分钟), doThisEverySecond最终会停止被调用。 When this occurs, the events that queued up during waitUntil periods fire all at once.发生这种情况时,在waitUntil期间排队的事件会立即全部触发。

Looks like my approach isn't the way to go.看来我的方法不是通往 go 的方法。

How do you call a function every second in a Chrome Extension Manifest V3 Background Service Worker?您如何在 Chrome Extension Manifest V3 Background Service Worker 中每秒调用 function?

I'm really sorry, but this isn't possible.真的很抱歉,但这是不可能的。

Now that we've got the official response out of the way: I don't have a good solution for you, but perhaps a hacky one will work?既然我们已经得到了官方的回应:我没有适合你的好解决方案,但也许一个 hacky 的解决方案会奏效?

I know you can create a named alarm in chrome, and have the onAlarm call a desired function. I reviewed the documentation and it doesn't seem like there's a limit to the number of named alarms you can create;我知道您可以在 chrome 中创建一个命名警报,并让onAlarm调用所需的 function。我查看了文档,您可以创建的命名警报的数量似乎没有限制; perhaps you can create 59 chrome.alarm s with an offset of 1000ms each?也许您可以创建 59 个chrome.alarm ,每个偏移量为 1000 毫秒?

Oh wait, you can't use setTimeout in a service worker.哦等等,你不能在 service worker 中使用setTimeout That's ok, I'll just make a brute-force timeout to set it up.没关系,我会强制超时来设置它。

function asyncDelay(msToDelay) {
  return new Promise((success, failure) => {
      var completionTime = new Date().getTime() + msToDelay
      while (true) {
        if (new Date().getTime() >= completionTime){
          success()
          break
        }
      }
      failure()
  })
}

Ok, so now I need to set up the 60 timers so they all fire 1 second after another.好的,所以现在我需要设置 60 个定时器,这样它们都会依次触发 1 秒。 Don't forget to call your tick() function while setting it up or it won't start running right away.不要忘记在设置时调用您的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 })
  }
}

Then we just need to trigger the tick when each alarm is finished.然后我们只需要在每次闹钟结束时触发滴答声。

chrome.alarms.onAlarm.addListener(() => {
  tick()
})

And some kind of behavior in the tick function to confirm it's working...勾选 function 中的某种行为以确认它正在工作......

async function tick() {
  console.log(new Date().getTime())
}

Tada!多田! Now tick() is called every 1000 ms!现在每 1000 毫秒调用一次tick()

Ahh crap.啊废话。

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

Ok, so it kind of worked, but some of the alarms fire at the same time.好吧,它有点管用,但一些警报同时响起。 Reviewing the documentation suggests that a 1 second granularity is not respected:查看 文档表明不遵守 1 秒的粒度:

In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more .为了减少用户机器上的负载,Chrome 将警报限制为最多每 1 分钟一次,但可能会延迟任意多的时间 That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning.也就是说,将 delayInMinutes 或 periodInMinutes 设置为小于 1 将不会被接受并会引起警告。 when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute. when 可以设置为在“现在”之后不到 1 分钟而不发出警告,但实际上不会导致至少 1 分钟的警报触发。

In my testing locally, I've been running this service worker without it going to sleep for ~10 minutes, and it's mostly ticking every second.在我的本地测试中,我一直在运行这个 service worker 大约 10 分钟,它不会休眠,而且它几乎每秒都在滴答作响。 It's not perfect, but I'm gonna consider this successful enough to submit.它并不完美,但我认为这足以提交。

Code is here: https://github.com/EyeOfMidas/second-tick-extension代码在这里: https://github.com/EyeOfMidas/second-tick-extension

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在清单 v3 Chrome 扩展程序中定期调用 function? - How do I call a function periodically in a manifest v3 Chrome extension? 后台 Chrome 扩展清单 V3 库 - Chrome Extension Manifest V3 Libraries in Background 如何分配键盘快捷键以在 Chrome Extension Manifest v3 中运行 function - How to assign Keyboard Shortcut to run a function in Chrome Extension Manifest v3 如何在 Chrome 扩展 Manifest V3 中存储敏感数据 - How to store sentitive data in Chrome extension Manifest V3 使用Chrome Extension Manifest V3,如何执行代码字符串? - Using Chrome Extension Manifest V3, How Do I Execute Code Strings? 在 Chrome 扩展中集成 GA,清单 v3 - Integrating GA in chrome extension, manifest v3 Chrome 扩展清单 v3 和内联脚本 - Chrome extension manifest v3 and inline scripts Chrome 扩展程序 - 尝试使用清单 v3 从后台脚本获取 () 时出现 CORS 错误 - Chrome Extension - Getting CORS error when trying to fetch() from background script with manifest v3 从后台执行内容脚本和关联的 CSS (Manifest V3) - Chrome 扩展 - Execute Content Script and associated CSS from Background (Manifest V3) - Chrome Extension 使用 Manifest V3 将 FormData/File 对象从内容脚本传递到 chrome 扩展中的后台脚本 - Passing FormData/File Object from content script to background script in chrome extension with Manifest V3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM