11

I have a client-side JS app that uses IndexedDB to store its state. Works fine. However, it's kind of slow because I am frequently reading from and writing to IndexedDB so that the state does not become inconsistent when multiple tabs are open.

My idea was... put all DB access stuff inside a Service Worker, and then I can cache values there in memory without worrying that another tab might have altered the database.

That seems to work fine, except some parts of my application take a long time to run. I can communicate the status (like "X% done") from the Service Worker to my UI. But both Firefox and Chrome seem to kill the worker if it runs for more than 30 seconds, which is way too short for me.

Is there any way around this limitation? If not, any ideas for achieving something similar? A Shared Worker could do it I think, except browser support is poor and I don't anticipate that improving now with the momentum behind Service Workers.

dumbmatter
  • 8,057
  • 5
  • 33
  • 71

3 Answers3

5

The Google documentation on service workers tells us that using service workers as a memory cache is impossible:

It's terminated when not in use, and restarted when it's next needed, so you cannot rely on global state within a service worker's onfetch and onmessage handlers. If there is information that you need to persist and reuse across restarts, service workers do have access to the IndexedDB API.

My suggestion is to keep using service workers to persist data to the database, and use localStorage to create a shared cache between pages. The tab that is making the change is then responsible for both updating the cache in localStorage and persisting to IndexedDB through the service worker.

Community
  • 1
  • 1
Borre Mosch
  • 3,584
  • 1
  • 16
  • 28
  • I already have the data in IndexedDB, and multiple tabs can access it... it's just slow to read and write to disk so much. localStorage would probably be even slower, if anything. After some more thought, I think a SharedWorker is pretty much exactly the solution I want, but MS/Apple are just never going to support it. – dumbmatter Jan 05 '17 at 02:05
4

I ended up using a Shared Worker. In browsers that don't support Shared Workers, such as Edge and Safari, I fall back to a Web Worker and some hacky code to only let you open the app in one tab at a time.

Since 90% of my users are on Firefox or Chrome anyway, I figure it's not a huge loss.

I also wrote a library to (amongst other things) normalize the APIs used in Shared Workers and Web Workers, so I have the exact same code running in both scenarios, the only difference is whether the worker is initialized with Worker or SharedWorker.

dumbmatter
  • 8,057
  • 5
  • 33
  • 71
0

As you said yourself SharedWorkers seems to be exactly what you need. I'm not sure why you think the momentum behind implementing ServiceWorkers prevent browsers from supporting SharedWorkers. They seem to be two different kind of beasts.

As far as I understand ServiceWorkers should be used as a proxy for your requests when your application is offline and heavy stuff should be done in WebWorkers and SharedWorkers

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker

Manis
  • 33
  • 4
  • http://caniuse.com/#feat=sharedworkers Safari used to support it, but removed it. Microsoft has no plans to support it. It is a different beast than Service Workers, but Service Workers have a ton of momentum, and at least some use cases overlap. – dumbmatter Feb 03 '17 at 00:32