I have a bit of code that gets looped and interrupted for a few seconds specified in a setTimeout
function, then the code is looped again once the delay is up. The problem that I'm facing is that when the page loses focus for a while, the timeout gets out of sync and the code is looped at "random" intervals other than what's specified in the setTimeout
delay.
Here's the current code for reference:
$(document).ready(function () {
for (var key in keys) {
element = key;
val = keys[key];
test(element, val);
(function loop(element, val) {
setTimeout(function () {
test(element, val);
loop(element, val);
}, 5000);
})(element, val);
}
});
I've searched around a bit and the issue seems to be expected and I'm trying to find the ideal workaround, thus far I've gone with the simpler approach which is to reload the entire page when it loses and then regains focus. It works but I'm not super happy with it.
Here's the current workaround:
$(window).blur(function(){
$(window).focus(function(){
location.reload();
});
});
I've also read about using clearTimeout
with focus
in an attempt to restart or sync the timeout but during many attempts I wasn't able to get something working properly. At best it would still throw the timeout out of whack in some form or another.
I'm at loss about which direction to take in order to get a more suitable approach than to refresh the webpage.
Thanks in advance for any suggestion.
I found a suitable answer in another question which works fine for my use case.
The suggestion is quite simple: avoid running code that depends on timed or throttled functions when the tab/page is not focused or, more accurately, when it is hidden from the user:
if (!document.hidden){ //your animation code here }
source: https://stackoverflow.com/a/53944438/924855
Although my issue is not related to animation, there is a commonality which is suffering from the throttling of setTimeout
when the page is not in view. Using this approach I avoid running code entirely when the page is not visible and it avoids de-syncing altogether, like so:
$(document).ready(function () {
for (var key in keys) {
element = key;
val = keys[key];
test(element, val);
(function loop(element, val) {
setTimeout(function () {
if (!document.hidden) {
test(element, val);
}
loop(element, val);
}, 5000);
})(element, val);
}
});