Ответ 1
Я не уверен, что это сработает или нет, я не могу проверить его сейчас, но попробую
$(window).focus(function() {
updater();
});
В моем веб-приложении используется метод "long poll", чтобы быть в курсе последних данных с моего сервера. Сервер реагирует только тогда, когда у него есть новые данные, которые могут находиться в нескольких минутах друг от друга. (Это система управления отоплением, в которой вы видите только обновления при изменении комнатной температуры или кто-то меняет настройки).
var version = "0";
function updater() {
$.ajax({
type: "POST",
url: "/listen",
data: version,
success: function (data) {
version = handleUpdates(data);
updater();
},
error: function () {
setTimeout(updater, 1000);
}
});
}
Он отлично работает на настольных браузерах и на телефонах, за исключением одного случая. Я обнаружил, что на телефонах Android с Chrome что-то странное случается после того, как телефон заснул более 10 минут. Пост-запрос, похоже, отбрасывается, и я думаю, это разумно, так как телефон спит. На вкладке "Сеть отладчика Chrome" текст состояния запроса POST говорит (отменен).
Проблема заключается в том, когда я разбудил телефон, пока запрос отменен, не вызывается функция success() или error(), и мое веб-приложение никогда не обновляется. $. ajax() нарушил свое обещание, чтобы перезвонить мне.
Проблема возникает только на некоторых устройствах. Я смог сделать несколько специальных тестов, заимствуя устройства у друзей. Пока я видел проблему только на телефонах Android. Но телефон не подключен к зарядному устройству. Я не видел его ни на каких планшетах, на яблочных устройствах или Windows-ПК.
Я попытался добавить тайм-аут к настройкам ajax:
timeout: 120 * 1000,
Это помогает, потому что функция error() в конечном итоге вызывается через 2 минуты после пробуждения. Но я хотел бы, чтобы пользователь видел обновления в течение 1 или 2 секунд. Я не хочу, чтобы тайм-аут был настолько коротким, что он создавал бы ненужный трафик сервера.
Я также попытался обнаружить, что устройство спит, ища опоздание за одну секунду setInterval, как описано в Могут ли какие-либо настольные браузеры обнаруживать, когда компьютер возобновляет сна?, Когда я обнаруживаю пробуждение, я прерываю() сообщение и запускаю другое. Это помогает в большинстве случаев. Но это оказывается ненадежным. Иногда временные события, похоже, обычно сохраняют тиканье во время сна, и почтовый запрос все равно отменяется. И это не похоже на надежное решение.
Я использую последнюю версию jQuery: (2.1.2) и Chrome (47).
Я не уверен, что это сработает или нет, я не могу проверить его сейчас, но попробую
$(window).focus(function() {
updater();
});
У меня были проблемы в прошлом, когда JavaScript-вызовы приостанавливались, когда телефон переспал. Решение, с которым я столкнулся, заключалось в использовании window.setInterval()
, который, кажется, приостанавливается, но возвращается к жизни, когда телефон проснулся.
Поэтому я бы рекомендовал установить интервал, который так часто отменяет вызов, и его повторно инициализирует. Это может помочь ему выжить через сон телефона.
Что-то примерно такое:
var myCall = $.ajax({...});
Window.setInterval (refreshCall(), 10000);
function refreshCall (){
myCall.abort ();
myCall = $.ajax({...});
}
Как насчет функции наблюдателя более высокого уровня:
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();
});
Вы знаете, что $(window). фокус срабатывает, когда телефон просыпается, поэтому вы пытаетесь обновить(), как предлагает Алмис, но с таймером с отказоустойчивостью. Если обновляется программа обновления (на ноутбуках или iOS), таймер отменяется, и все в порядке, но если программа обновления мертва, таймер отказоустойчивости срабатывает через 6 секунд и перезагружает все ваше приложение, вызывая initializeAll().
Как насчет setInterval
, в котором хранится время его вызова, затем сравнивается последний раз, когда он был вызван в текущее время - если ваш интервал составляет 10 секунд, а время, прошедшее с момента последнего прогона, составляло 5 минут, вы может предположить, что вы только что проснулись от сна? Затем отмените текущий вызов ajax и перезапустите его.
Лучший ответ - "не делай этого". У вас есть сервер, ожидающий ответа, когда он отслеживает изменения на стороне сервера. Просто ответьте на сервер и выполните ping jQuery с интервалом. Вы можете включить lastchanged или haschanged, если хотите предотвратить фактическое обновление, когда нет изменения статуса, но если сервер выполняет одну и ту же работу в любом случае, просто позвольте ему ответить и ждать следующего опроса.
setInterval(function () {
$.post({"/listen", version, function (data) {
if(data.haschanged)
version = handleUpdates(data);
}).fail(function () {
// any error correction on failed call
});
}, 1000);