tutorial pwa gratis facil español desde create cero apps app service-worker

service worker - pwa - ¿Cuándo se ejecuta el código en un trabajador de servicio fuera de un controlador de eventos?



pwa service worker generator (1)

(Parafraseando la pregunta formulada por Rich Harris en la sección " Cosas que desearía haber sabido antes acerca de los trabajadores de servicios ").

Si tengo un código en mi trabajador de servicio que se ejecuta fuera de un controlador de eventos, ¿cuándo se ejecuta?

Y, estrechamente relacionado con eso, ¿cuál es la diferencia entre colocar dentro de un controlador de install y ponerlo completamente fuera de un controlador de eventos?


En general, el código que está fuera de cualquier controlador de eventos, en el "nivel superior" del alcance global del trabajador del servicio, se ejecutará cada vez que se inicie el subproceso (/ proceso) del trabajador del servicio. El subproceso del trabajador de servicios puede comenzar (y detenerse) en momentos arbitrarios, y no está ligado a la vida útil de las páginas web que controlaba.

(Iniciar / detener el subproceso del trabajador de servicio con frecuencia es una optimización de rendimiento / batería, y garantiza que, por ejemplo, solo porque navega a una página que ha registrado un trabajador del servicio, no obtendrá un subproceso inactivo extra en segundo plano. )

La otra cara de esto es que cada vez que se detiene el subproceso del trabajador de servicios, se destruye cualquier estado global existente. Entonces, si bien puede realizar ciertas optimizaciones, como almacenar una conexión abierta de IndexedDB en un estado global con la esperanza de compartirla en múltiples eventos, debe estar preparado para reinicializarlas si se eliminó el hilo entre las invocaciones del controlador de eventos.

Muy relacionado con esta pregunta es un error que he visto sobre el controlador de eventos de install . He visto a algunos desarrolladores usar el controlador de install para inicializar el estado global en el que se basan en otros controladores de eventos, como fetch . Esto es peligroso, y probablemente dará lugar a errores en la producción. El controlador de install activa una vez por versión de un trabajador del servicio, y normalmente se usa mejor para tareas relacionadas con el control de versiones del trabajador del servicio, como el almacenamiento en caché de recursos nuevos o actualizados que necesita esa versión. Una vez que el controlador de install haya completado con éxito, una versión dada de un trabajador de servicio se considerará "instalada", y el controlador de install no se activará nuevamente cuando el trabajador de servicio se inicie para manejar, por ejemplo, un evento de fetch o message .

Por lo tanto, si hay un estado global que deba inicializarse antes de manejar, por ejemplo, un evento de fetch , puede hacerlo en el ámbito global del trabajador de servicio de nivel superior (opcionalmente, esperar en una promesa para resolver dentro del controlador de eventos de fetch para asegurar que cualquier operación asíncrona se haya completado). ¡ No confíe en el controlador de install para configurar el alcance global!

Aquí hay un ejemplo que ilustra algunos de estos puntos:

// Assume this code lives in service-worker.js // This is top-level code, outside of an event handler. // You can use it to manage global state. // _db will cache an open IndexedDB connection. let _db; const dbPromise = () => { if (_db) { return Promise.resolve(_db); } // Assume we''re using some Promise-friendly IndexedDB wrapper. // E.g., https://www.npmjs.com/package/idb return idb.open(''my-db'', 1, upgradeDB => { return upgradeDB.createObjectStore(''key-val''); }).then(db => { _db = db; return db; }); }; self.addEventListener(''install'', event => { // `install` is fired once per version of service-worker.js. // Do **not** use it to manage global state! // You can use it to, e.g., cache resources using the Cache Storage API. }); self.addEventListener(''fetch'', event => { event.respondWith( // Wait on dbPromise to resolve. If _db is already set, because the // service worker hasn''t been killed in between event handlers, the promise // will resolve right away and the open connection will be reused. // Otherwise, if the global state was reset, then a new IndexedDB // connection will be opened. dbPromise().then(db => { // Do something with IndexedDB, and eventually return a `Response`. }); ); });