3

Is there a way to tell that the SharedWorker is about to get closed, something like the beforeunload event that window has?

I need this information inside of the worker to signal server of closing of web socket etc.

Akxe
  • 9,694
  • 3
  • 36
  • 71
  • It's hard to prove a negative and I haven't used shared workers enough to feel confident posting this as an answer, but it doesn't look like the worker receives any kind of warning. There's nothing about it in MDN ([here](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker), [here](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope)) and the "[terminate a worker](https://html.spec.whatwg.org/multipage/workers.html#terminate-a-worker)" operation in specification for workers doesn't show any notification step. (That op is for all workers, not just dedicated.) – T.J. Crowder Feb 02 '22 at 13:46
  • That part looks into the normal worker, the shared worker has no mention of closing/terminating... thought I suppose they both extend the same AbstractWorker... – Akxe Feb 02 '22 at 16:52
  • As I said, that operation is for all workers, not just dedicated ones. It's referenced by [this section on shared workers](https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworkerglobalscope-interface). – T.J. Crowder Feb 02 '22 at 16:55

2 Answers2

2

No.

But SharedWorker will be alive as long as there is any live page holding a reference to it (through new SharedWorker()). So what you can do is to post a message to your SharedWorker when your page is about to go away (pagehide event), and your SharedWorker can keep track of how many pages are alive and close the WebSocket when the live count drops to zero.

However, do watch out for the definition of "live page". Chrome (and other browsers as well) tries very hard to optimize the browser performance and energy impact. Chrome has this Tab Discarding feature where it will discard background pages when there is pressure on the memory. Discarding a page will throw away the page data without closing the window, so that when user clicks the windows again Chrome can reload the page. This usually isn't an issue for simple website, but given that you are running websocket inside SharedWorker this could have some implications on your overall protocol design. In particular, if all of your pages are discarded, your SharedWorker dies as well. And discarding a page has absolutely zero notification.

Xinchao
  • 2,929
  • 1
  • 24
  • 39
  • "And discarding a page has absolutely zero notification." Doesn't Chrome support the [onfreeze](https://github.com/WICG/page-lifecycle#api) event yet? It seems to be available to me. – Kaiido Apr 01 '22 at 10:08
  • Actually, there is a better way I found out: https://stackoverflow.com/questions/13662089/javascript-how-to-know-if-a-connection-with-a-shared-worker-is-still-alive/71499332#71499332 The point is, that the port is held as long as the window it belongs to is alive, thus watching its presence is a way to detect if it is still alive. Possibly FinalizationRegistry would be better – Akxe Apr 01 '22 at 14:16
  • 1
    @Kaiido discard is different from freeze. When a page is frozen it is not discarded yet, and it can be resumed later. Discarding a page is more like Chrome kills your page. The reason from Chrome to discard your page is because Chrome senses a pressure on memory, and just like OutOfMemory exception, Chrome cannot notify the application because there is no resource left for the application to handle such an event. Open a page and navigate to chrome://discards, pick your page and click urgent discard, you will see what happens – Xinchao Apr 02 '22 at 13:51
  • @Akxe The problem with using a WeakRef is that you have to periodically check the ref yourself, this is technically similar to periodically ping the window and expect a reply to assert the window is alive, effectively a heartbeat mechanism. When all of your windows are closed, your SharedWorker will be terminated as well regardless of whether you have a timer in your SharedWorker. So chances are you will not be able to run your timer check to realize all the windows are gone. – Xinchao Apr 02 '22 at 14:00
  • @Xinchao `FinalizationRegistry` is also an option... I am not sure when does shared worker is to be closed. – Akxe Apr 02 '22 at 15:48
  • @Akxe yea, but it is a similar thing as WeakRef. Just like the finalization mechanism in other languages, this one seems to be a best-effort thing. E.g. there is no guarantee if and when your callback will be called. Especially when the page is unloading, given that your entire "program" is going away anyway, your callback may not be called at all because the callback is only supposed to eagerly release some resource (which will be released anyway after the page is trashed). – Xinchao Apr 03 '22 at 10:28
  • True, it does not solve the closing of the last page problem, but due to the way it is written, nothing will... – Akxe Apr 04 '22 at 10:49
0

you can read about it in 10.2.3 The worker's lifetime! section. Here it is mentioned that a shared worker is permissible as long as

  • the user agent has a navigable whose active document is not completely loaded. So once the active document is loaded completely it no longer alive.
  • Other condition is that its owner set has been empty for more than a short implementation-defined timeout value
Ambuj sahu
  • 68
  • 1
  • 6
  • I have read the specification, but the reason I needed the event, is so that I inform the server of self-closure, thus free server resources... This is not helpful. – Akxe Jan 11 '23 at 11:00