It's a little difficult to debug this fully without seeing your example code, but a general rule of thumb would be that if you're scheduling asynchronous work that you want done outside of the synchronous execution of a service worker event handler, you need to
- schedule that work from inside of a
ExtendableEvent
and
- wrap the work by passing a promise for its completion to the
waitUntil()
method of that ExtendableEvent
.
(FetchEvent
is an ExtendableEvent
.)
If you fail to do that, then the browser does not guarantee that your asynchronous task will complete before the service worker thread is killed. Different browsers are more or less aggressive about terminating the service worker thread, so that might explain the different behavior you're seeing.
lodash's debounce()
does not offer built-in support for promises, so you'll either have to wrap things yourself, or find a suitable alternative library. Just note that whatever approach you use, make sure that you use promises that will eventually resolve, even if the operation is debounced. Otherwise, if you pass a promise that doesn't resolve to waitUntil()
, you'll end up keeping the service worker alive much too long.
Putting aside the actual implementation of a promise-returning debounceWithPromises()
, the general structure would look like:
self.addEventListener('fetch', (event) => {
if (/* some criteria is met */) {
// As soon as the promise passed to respondWith() resolves,
// the response will start being fed to the client.
event.respondWith(generateResponse(event);
// Independent of the response generation, the promise returned
// by the hypothetical debounceWithPromises() will keep the
// service worker alive until it resolves or rejects (or until a
// browser-specific maximum lifetime is reached).
event.waitUntil(debounceWithPromises(logStats));
}
});