Have a Question?

If you have any question you can ask below or enter what you are looking for!

Question Detial

My web app uses the 'long poll' method to keep up to date with the latest data from my server. The server only responds when it has new data, which can be many minutes apart. (It is a heating control system where you only see updates when room temperatures changes or somebody changes the settings).

var version = "0";
function updater() {
    $.ajax({
        type: "POST",
        url: "/listen",
        data: version,
        success: function (data) {
            version = handleUpdates(data);
            updater();
        },
        error: function () {
            setTimeout(updater, 1000);
        }
    });
}

It works fine on desktop browsers and on phones except in one case. I have found that on android phones with Chrome something odd happens after the phone has gone to sleep for more then about 10 minutes. The post request seems to be dropped, which I guess is reasonable since the phone is asleep. In the Chrome debugger's Network tab, the Status Text of the POST request says (canceled).

The problem is when I wake the phone up while the request is cancelled, neither the success() or error() function is called, and my web app never gets updated. $.ajax() has broken its promise to call me back.

The problem only happens on some devices. I have been able to do a few ad-hoc tests by borrowing devices off friends. So far I have only seen the problem on android phones. But not is the phone is connected to a charger. I have not seen it on any tablets, on apple devices or windows PCs.

I have tried adding a timeout to the ajax settings:

     timeout: 120 * 1000,

This helps because the error() function is eventually called up to 2 minutes after the wake up. But I'd like the user to see updates within 1 or 2 seconds. I don't want to make the timeout so short because it would create unnecessary server traffic.

I have also tried detecting whether device is asleep by looking for lateness in a one second setInterval as described in Can any desktop browsers detect when the computer resumes from sleep?. When I detect the wake up, I abort() the post and start another. This helps in most cases. But it turns out to be unreliable. Sometimes time events seem to keep ticking normally during sleep and the post request gets cancelled anyway. And it it does not feel like a reliable fix.

I am using latest version of jQuery: (2.1.2) and Chrome (47).

Answers

Jon Skeet

12:13pm 17th December 2015

I not sure this will work or not, I cannot test it now but give it a try

$(window).focus(function() {
    updater();
});

Sven Marnach

4:53pm 21st December 2015

I've had problems in the past with JavaScript calls getting suspended when the phone goes to sleep. The solution I ended up with was to use window.setInterval() which seems to suspend, but come back to life when the phone is woken up.

So I would recommend setting an interval which cancels the call every so often and reinitiates it. This might help it survive through a phone sleep.

Something roughly like:

var myCall = $.ajax({...});

Window.setInterval (refreshCall(), 10000);

function refreshCall (){
    myCall.abort ();
    myCall = $.ajax({...});
}

Mike Patrick

9:03am 26th October 2016

How about a higher-level watcher function like this:

var restartTimer = null;
function updater(){
    $.ajax({
        type: "POST",
        url: "/listen",
        data: version,
        success: function (data) {
            version = handleUpdates(data);
            clearTimeout(restartTimer);
            updater();
        },
        error: function () {
            clearTimeout(restartTimer);
            setTimeout(updater, 1000);
        }
    });
}
//  Kick it when the phone wakes up.
$(window).focus(function(){
    restartTimer = setTimeout(function(){
        initializeAll();
    }, 6000);
    updater();
});

You know that the $(window).focus will fire when the phone wakes up, so you try updater() as Almis suggests, but with a fail-safe timer. If updater fires (on laptops or iOS), the timer is canceled and all is well, but if updater is dead, the fail-safe timer fires in 6 seconds and reboots your entire app by calling initializeAll().

Mike Patrick

6:50am 7th December 2017

How about a setInterval, that stores the time it was called, then compares the last time it was called to the current time - if your interval is 10 seconds and the time passed since the last run was 5 minutes, you can assume you've just woken from sleep? Then abort the current ajax call, and restart it.