(i paraphrasing question asked rich harris in "stuff wish i'd known sooner service workers" gist.)
if have code in service worker runs outside event handler, when run?
and, closely related that, difference between putting inside install
handler , putting outside event handler entirely?
in general, code that's outside event handler, in "top-level" of service worker's global scope, run each , every time service worker thread(/process) started up. service worker thread may start (and stop) @ arbitrary times, , it's not tied lifetime of web pages controlled.
(starting/stopping service worker thread performance/battery optimization, , ensures that, e.g., because browse page has registered service worker, won't idle thread spinning in background.)
the flip side of every time service worker thread stopped, existing global state destroyed. while can make optimizations, storing open indexeddb connection in global state in hopes of sharing across multiple events, need prepared re-initialize them if thread had been killed in between event handler invocations.
closely related question misconception i've seen install
event handler. have seen developers use install
handler initialize global state rely on in other event handlers, fetch
. dangerous, , lead bugs in production. install
handler fires once per version of service worker, , best used tasks tied service worker versioning—like caching new or updated resources needed version. after install
handler has completed successfully, given version of service worker considered "installed", , install
handler won't triggered again when service worker starts handle, e.g., fetch
or message
event.
so, if there global state needs initialized prior handling, e.g., fetch
event, can in top-level service worker global scope (optionally waiting on promise resolve inside fetch
event handler ensure asynchronous operations have completed). not rely on install
handler set global scope!
here's example illustrates of these points:
// assume code lives in service-worker.js // top-level code, outside of event handler. // can use manage global state. // _db cache open indexeddb connection. let _db; const dbpromise = () => { if (_db) { return promise.resolve(_db); } // assume we're using 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` fired once per version of service-worker.js. // **not** use manage global state! // can use to, e.g., cache resources using cache storage api. }); self.addeventlistener('fetch', event => { event.respondwith( // wait on dbpromise resolve. if _db set, because // service worker hasn't been killed in between event handlers, promise // resolve right away , open connection reused. // otherwise, if global state reset, new indexeddb // connection opened. dbpromise().then(db => { // indexeddb, , return `repsonse`. }); ); });
Comments
Post a Comment