4

Just notice that Safari 10.0.3 delay my code when the page is in a background tab.

var interval = 2000;
var scriptTime = new Date().getTime();
function addTime(){
    scriptTime += interval;
    document.getElementById('output').innerHTML = "Current state: scripts delayed by "+(new Date().getTime()-scriptTime)+"ms";
}
setInterval(addTime, interval);

Try here: https://jsfiddle.net/rhrrsgrf/4/

Found some confirmation of optimization with small interval, but nothing about timer bigger than 1 second (still hope that's only a bug...). Chrome 56 seems to have something similiar (https://www.ghacks.net/2017/01/25/chrome-to-throttle-expensive-background-timers/), but isn't impacting my code.

Any other simple solution to send a ping (30 sec) to a server?

c3k
  • 81
  • 7
  • It's actually worse than this. Safari caps intervals at 1000ms and then adds its own exponential delay, doubling every iteration. – twistedpixel May 01 '17 at 15:26

1 Answers1

0

I have found that having a Worker handle background threads helps somewhat. Create another javascript file:

// worker.js
const poll_url = "https://stackoverflow.com/"
setInterval(function() {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200)
            self.postMessage(xhr.responseText);
    };
    xhr.open("GET", poll_url, true);
    xhr.send(null);
}, 5000);

And in your main code:

let worker = new Worker("worker.js");
worker.onmessage = function (data) {
    // handle your poll response here
};

This will prevent any exponential time skips. In Safari I have seen up to 4 second delay spikes, but never constant delays. For anything over 5 seconds between polls, this tends to work well for me.

I have observed that in Chrome, Firefox and Opera this works perfectly. As long as function in the worker is not too demanding (polling is fine), there are no noticable delays. In Safari, I generally expect to see few spikes in delay of up to 4 seconds early on, possibly as it switches to background, and then it becomes consistent.

If you need to catch up to potential delays, you can use recursive setTimeout and subtract the delay from the next timeout value by keeping track of when the last request was sent.

Mirac7
  • 1,566
  • 4
  • 26
  • 44
  • Code converted: with workers I have the same behavior. I still can't have a reliable way to send a ping from Safari. – c3k May 13 '19 at 09:50