I'm writing a browser game using HTML, CSS and JavaScript, written in Perl. Health and stamina are saved on the server and I use JavaScript to show the user a live updated count of these stats when the current page loads. This feature works well, but if the user switches tabs or switches to another app and leaves the browser running in the background, the count value you see when you return doesn't keep up properly. So when you switch back to the browser, your counter may show 50/100 stamina, when in fact your stamina is 100/100. So when you do something in the game (load a new page), the server updates the counter to a real value, because the JavaScript is just timing to show a "live" scroll view to the user in the browser.
Is there a way to ensure that JavaScript counters still work even if the page/tab is inactive or not in the foreground? Short of completely rewriting my game to display a continuous stream of live server push content to the user in the browser?
Suppose you are playing a game. You'll see your health and stamina return. You switch to another program for a minute, then return to the game in the browser. You will notice that health and stamina are not updated while you are away. But when you perform an action in the game, the value will be updated to what it should be because it's tracked internally on the server. This is the problem I want to solve. Hope that makes it clear!
I haven't tried anything to solve this problem other than searching online and ultimately finding no really "good" answer on this site, so I decided to ask.
Continuous server push also doesn't work. Anything in the main event loop, such as timers or events that occur when focus is lost, will be slowed down by the browser to save resources. Some mobile browsers stop it entirely.
The answer to the problem is to change how the application tracks these statistics.
Now some people will say to use WebWorkers to run the timer in a separate thread, but this does not solve all problems. You'll still have issues with different versions, like if someone resumes your page from sleep or something like that. No background tasks survive.
You mentioned that you also track these statistics on the server. This is convenient, so the most obvious thing you should do is use Window Focus Events to detect when a label regains focus. You would then call the server to get the latest statistics and reset the timer based on that new data. To prevent stale data from being displayed while a request is in progress, you can choose to display a loading spinner or something else during this time.
Another common way to fix this is to keep a variable each time the timer increments that represents the timestamp when data was last returned. When you lose focus you can detect using the
blur
event and store that last timestamp somewhere. Then when they regain focus you can handle thefocus
event and calculate the difference between the current time and the last time recorded before leaving focus (losing focus). You can recalculate from this period what the value should be.But if your server has this information, it would be less error-prone and simpler to just ask the server when focus is regained.