Los trabajadores del servicio reemplazan las páginas de fondo en Manifest v3 Google Chrome Extensions, y estoy tratando de usar una para mi extensión. La documentación dice que se deben evitar los temporizadores ( setTimeout y setInterval ) porque los temporizadores se cancelan cuando los trabajadores del servicio terminan (lo que puede suceder en cualquier momento). A diferencia de las páginas de fondo, los trabajadores del servicio no pueden ser persistentes y siempre estarán sujetos a terminación. La documentación recomienda utilizar la API de alarmas en su lugar.
Necesito poder ejecutar una función periódicamente en un trabajador de servicio Manifest v3, pero las alarmas no se adaptan a mi caso de uso porque son lentas. La duración de alarma más corta permitida es de 1 minuto, pero quiero ejecutar una función en intervalos más cortos: un segundo o unos pocos segundos.
Intenté usar event.waitUntil para mantener vivo al trabajador del servicio según esta respuesta de desbordamiento de pila. Aquí está mi intento de solución para imitar un setInterval de 1 segundo con la repetición de llamadas waitUntil :
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'); };Tiene grandes problemas:
Dado que event.waitUntil hace que el despachador de eventos espere, estos eventos no se activan cuando mi bootleg setInterval se está ejecutando:
chrome.tabs.onUpdated.addListener(…); chrome.tabs.onReplaced.addListener(…); chrome.runtime.onMessage.addListener(…); Y descubrí que doThisEverySecond finalmente deja de recibir llamadas si se deja que el trabajador del servicio se ejecute durante algún tiempo, como unos minutos. Cuando esto ocurre, los eventos que se pusieron en cola durante los períodos waitUntil se activan todos a la vez.
Parece que mi enfoque no es el camino a seguir.
¿Cómo se llama a una función cada segundo en un Chrome Extension Manifest V3 Background Service Worker?
Lo siento mucho, pero esto no es posible.
Ahora que tenemos la respuesta oficial fuera del camino: no tengo una buena solución para usted, pero tal vez funcione una hacky.
Sé que puede crear una alarma con nombre en Chrome y hacer que onAlarm llame a la función deseada. Revisé la documentación y no parece que haya un límite para la cantidad de alarmas con nombre que puede crear; ¿tal vez pueda crear 59 chrome.alarm s con un desplazamiento de 1000 ms cada uno?
Oh, espera, no puedes usar setTimeout en un trabajador de servicio. Está bien, solo haré un tiempo de espera de fuerza bruta para configurarlo.
function asyncDelay(msToDelay) { return new Promise((success, failure) => { var completionTime = new Date().getTime() + msToDelay while (true) { if (new Date().getTime() >= completionTime){ success() break } } failure() }) } Bien, ahora necesito configurar los 60 temporizadores para que todos disparen 1 segundo tras otro. No olvide llamar a su función tick() mientras la configura o no comenzará a ejecutarse de inmediato.
async function run() { for(let i = 0; i < 60; i++) { tick() await asyncDelay(1000) chrome.alarms.create(`recurring-polling-thread-${i}`, { periodInMinutes:1 }) } }Entonces solo tenemos que activar el tic cuando finalice cada alarma.
chrome.alarms.onAlarm.addListener(() => { tick() })Y algún tipo de comportamiento en la función de tic para confirmar que está funcionando...
async function tick() { console.log(new Date().getTime()) } ¡Tada! ¡Ahora tick() se llama cada 1000 ms!
Ah mierda.
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 1647382809642Bien, funcionó, pero algunas de las alarmas se disparan al mismo tiempo. Revisar la documentación sugiere que no se respeta una granularidad de 1 segundo:
Para reducir la carga en la máquina del usuario, Chrome limita las alarmas a una vez cada 1 minuto como máximo, pero puede retrasarlas una cantidad arbitraria más . Es decir, establecer delayInMinutes o periodInMinutes en menos de 1 no se respetará y generará una advertencia. when se puede configurar en menos de 1 minuto después de "ahora" sin previo aviso, pero en realidad no hará que la alarma se dispare durante al menos 1 minuto.
En mi prueba local, he estado ejecutando este trabajador de servicio sin que entre en modo de suspensión durante aproximadamente 10 minutos, y en su mayoría funciona cada segundo. No es perfecto, pero lo consideraré lo suficientemente exitoso como para enviarlo.
El código está aquí: https://github.com/EyeOfMidas/second-tick-extension