Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect when browser throttles timers and websockets disconnection after a user leaves a tab or turns off the screen? (javascript)

Tags:

Context

A game shipped as a progressive web app which has timers (setTimeout, setInterval) and websocket connections to get real-time communication.

What is happening

Everything is fine as long as the user stays in the app. But when the user goes to another tab, or another app or turns off the screen (in case of mobile), it becomes a "hellish unknown world".

  • Websockets may or may not become "paused" or "turned off"
  • Timers look like they are being throttled or debounced.

This behaviour seems to depend on browsers and platform and, maybe, even depend on the particular user behaviour. I guess browsers and OS have their own lifecycle / mechanisms to save battery and/or computation.

When the user comes back, the app is in an unknown state and I am struggling to restore the state properly.

Regarding websockets I have auto-reconnection with socket.io and reconnecting-websocket but it's not enough to solve everything.

Looking for answers

  • What are the "lifecycles" of the different browsers regarding these? Is this documented? When do they decide to turn off and throttle?
  • What do they do exactly to websockets? Browsers just disconnect them?
  • What do they do exactly to timers? They throttle them or debounce them or something else?
  • What happens to javascript execution in general? Paused / destroyed / throttled?
  • Is there a way to hook into some kind of browser lifecycle event when it's going to turn things off? The only thing I could find might be the visibility API
  • Is there a way to artificially reproduce this behaviour to be able to test solutions? It's especially hard on desktop. Websockets can't be turned off and chromium developers don't seem in a hurry to help an issue from 2014(!): websockets not included when using connection throttling

  • Regardless of the above, is there a pragmatic cross-browser solution to detect / solve this problem? (for example from experience, Firefox on desktop seems to behave completely different compared to Chrome, and an iPhone will disconnect far more often than an Android)

Related Links

  • Safari dropping web socket connection due to inactivity when page not in focus
like image 863
Kev Avatar asked Mar 19 '20 13:03

Kev


People also ask

How do I stop WebSockets from disconnecting?

disable the feature "Intensive throttling of Javascript timer wake ups" in Chrome or, 2. change the web-transport inactive-timeout in the client profile to more than 60 seconds. To disable the Chrome feature, key in "chrome://flags" in Chrome URL field, search for "Throttle Javascript timer" and disable the feature.

How do I know if a WebSocket is disconnected?

You can check if a WebSocket is disconnected by doing either of the following: Specifying a function to the WebSocket. onclose event handler property, or; Using addEventListener to listen to the close event.

What causes WebSocket disconnect?

By default, if a ping has not been received in 60 seconds, and the connection has been otherwise inactive, the platform will close the WebSocket. This timeout is configurable in the WS Communication Subsystem configuration, Idle Connection Timeout (sec) parameter.


2 Answers

Not exactly sure, but you could use service workers. As much as I know, they run in background even if your tab is not opened and get terminated if your tab closes.

Btw. lifecycles of browser tabs seem to be different on every browser, since every browser handles it different. From what I see the browser can freeze tabs if it needs more memory for other things.

Here is the docs from Chrome.

I remembered that there are some events, like onload that tell you if a user has left or reopened the tab. You could use these event to reconnect etc..

like image 163
Mointy Avatar answered Oct 16 '22 05:10

Mointy


I would give different advice regarding how to design your app. From what I understand your intention is to add more logic in order to understand if the user is no longer active in the browser. This entails a different problem which is browser specifics to implement that logic. With that in mind, I would instead invest in have better error handling, both in the server and client.

Errors won't be browser-specific. Handling those will make your app more resilient and agnostic to browser changes, that could eventually change, let's say, the way they hibernate a tab, any other feature that a vendor might implement in the future.

This is an idea that you can find in services architecture, but the same pattern applies to any web-app. You might want to look for Design-for-Fail concepts:

Complexity makes it infeasible to assume robustness on the part of the systems upon which one relies. Instead, one needs to design systems and applications at any given layer in the IT stack-based to assume the possibility of failure at lower levels. Design-for-fail necessitates thinking about fault tolerance at all layers. No longer can application developers confine themselves to thinking about functionality.

https://www.oreilly.com/library/view/designing-delivery/9781491903742/ch04.html

like image 42
a--m Avatar answered Oct 16 '22 03:10

a--m