后台选项卡中的Safari延迟setInterval / setTimeout(间隔> 1000毫秒)

时间:2017-02-10 10:45:25

标签: javascript safari background settimeout setinterval

请注意,当页面位于后台标签页时,Safari 10.0.3会延迟我的代码。

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);

在此尝试:https://jsfiddle.net/rhrrsgrf/4/

找到一些小间隔优化的确认,但没有关于大于1秒的计时器(仍然希望这只是一个错误......)。 Chrome 56似乎有类似的东西(https://www.ghacks.net/2017/01/25/chrome-to-throttle-expensive-background-timers/),但不影响我的代码。

将ping(30秒)发送到服务器的任何其他简单解决方案?

1 个答案:

答案 0 :(得分:0)

我发现使用Worker处理后台线程会有所帮助。创建另一个JavaScript文件:

// 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);

在您的主要代码中:

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

这将防止任何指数时间跳跃。在Safari中,我看到了最多4秒钟的延迟峰值,但从未出现持续的延迟。在两次民意调查之间超过5秒的时间,这对我来说效果很好。

我观察到,在Chrome,Firefox和Opera中,这非常有效。只要工人的功能要求不高(轮询很好),就不会出现明显的延迟。在Safari中,我通常希望在最早到4秒的延迟中看到很少的峰值,可能是因为它切换到了后台,然后变得一致。

如果需要赶上潜在的延迟,可以使用递归setTimeout并通过跟踪上次请求的发送时间从下一个timeout值中减去延迟。