2015-12-17 5 views
11

Meine Webanwendung verwendet die Methode 'lang poll', um mit den neuesten Daten von meinem Server auf dem neuesten Stand zu bleiben. Der Server reagiert nur auf neue Daten, die viele Minuten auseinander liegen können. (Es ist ein Heizungssteuerungssystem, in dem Sie nur Aktualisierungen sehen, wenn sich die Raumtemperatur ändert oder jemand die Einstellungen ändert).Long-Poll jQuery.ajax() schlägt fehl, nachdem Telefon schläft?

Es funktioniert gut auf Desktop-Browsern und auf Handys außer in einem Fall. Ich habe festgestellt, dass auf Android-Handys mit Chrome etwas seltsam passiert, nachdem das Telefon für mehr als etwa 10 Minuten eingeschlafen ist. Die Post-Anfrage scheint fallen gelassen zu werden, was ich für vernünftig halte, da das Telefon schläft. Auf der Registerkarte "Netzwerk" des Chrome-Debuggers wird der Statustext der POST-Anforderung angezeigt (abgebrochen).

Das Problem ist, wenn ich das Telefon wecken, während die Anfrage abgebrochen wird, weder die Funktion success() oder error() aufgerufen wird, und meine Web-App wird nie aktualisiert. $ .ajax() hat sein Versprechen gebrochen, mich zurückzurufen.

Das Problem tritt nur bei einigen Geräten auf. Ich konnte einige Ad-hoc-Tests durchführen, indem ich Geräte von Freunden entlehnt habe. Bis jetzt habe ich nur das Problem auf Android-Handys gesehen. Aber nicht ist das Telefon an ein Ladegerät angeschlossen. Ich habe es auf keinem Tablet, auf Apple-Geräten oder Windows-PCs gesehen.

Ich habe versucht, einen Timeout auf die Ajax-Einstellungen hinzugefügt:

 timeout: 120 * 1000, 

Dies trägt dazu bei, da die Fehler() Funktion schließlich bis zu 2 Minuten nach dem Aufwachen genannt wird. Aber ich möchte, dass der Benutzer Updates innerhalb von 1 oder 2 Sekunden sieht. Ich möchte das Timeout nicht so kurz machen, weil es unnötigen Serververkehr verursachen würde.

Ich habe auch versucht, zu erkennen, ob das Gerät schläft, indem ich nach einer Verspätung in einer Sekunde setInterval suche, wie in Can any desktop browsers detect when the computer resumes from sleep? beschrieben. Wenn ich den Aufweck erfahre, breche ich den Post ab und starte einen anderen. Dies hilft in den meisten Fällen. Aber es erweist sich als unzuverlässig. Manchmal scheinen Zeitereignisse während des Schlafs normal zu ticken und die Postanforderung wird trotzdem abgebrochen. Und es fühlt sich nicht wie eine zuverlässige Lösung an.

Ich benutze die neueste Version von jQuery: (2.1.2) und Chrome (47).

+0

versuchen Sie, die aktuelle Zusage global zu speichern. Wenn Sie diesen fehlgeschlagenen Status eingeben, überprüfen Sie die .state() der Zusage. Was enthält es? Wenn es etwas anderes als "pending" enthält, können Sie es zusammen mit der Lösung von @ spozun verwenden, um die Dinge nach einer Schlafperiode zu starten, ohne die Anfragen unnötig zu löschen. –

Antwort

0

ich nicht sicher, ob dies funktionieren wird oder nicht, kann ich es jetzt nicht testen, aber geben Sie es versuchen, ein

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

Wäre das nicht eine weitere Anfrage in Fällen, in denen der Browser wie erwartet funktioniert und die Anfrage offen lässt? – Katana314

+0

@ Katana314 dies wird nur ausgelöst, wenn Benutzer auf anderen Tab war (ich denke, funktioniert auch für inaktive auf dem Handy) und Fokussierung meines Tabs. Natürlich können Sie auch eine Art Flag verwenden, um zu sehen, ob Updater wie erwartet funktioniert. – Almis

+0

Leider funktioniert das nicht. Es hat es versucht. $ (window) .focus() ruft die Funktion nicht auf, wenn das Telefon aus dem Ruhezustand erwacht. Es scheint nur die Funktion aufzurufen, wenn Sie zwischen den Tabs in Chrome wechseln. – James

0

Ich habe in der Vergangenheit hatten Probleme mit Anrufen JavaScript suspendiert wurden, wenn das Telefon zu schlafen geht. Die Lösung, mit der ich endete, war die Verwendung von window.setInterval(), die scheinbar auszusetzen ist, aber wieder zum Leben erweckt wird, wenn das Telefon aufgeweckt wird.

Also würde ich empfehlen, ein Intervall zu setzen, das den Anruf immer wieder abbricht und neu initialisiert. Dies könnte helfen, durch einen Telefonschlaf zu überleben.

Etwas grob wie:

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

Window.setInterval (refreshCall(), 10000); 

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

Wie wärs mit einer höheren Ebene watcher Funktion wie folgt aus:

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

Sie wissen, dass die $ (Fenster) .focus ausgelöst wird, wenn das Telefon aufwacht , also versuchen Sie updater() wie Almis vorschlägt, aber mit einem ausfallsicheren Timer.Wenn Updater ausgelöst wird (auf Laptops oder iOS), wird der Timer abgebrochen und alles ist gut, aber wenn der Updater inaktiv ist, wird der fehlersichere Timer in 6 Sekunden ausgelöst und startet die gesamte App neu, indem er initializeAll() aufruft.

0

Wie wärs mit einem setInterval, dass die Zeit speichert er genannt wurde, dann das letzte Mal, vergleicht sie mit der aktuellen Zeit genannt wurde - wenn Ihr Intervall 10 Sekunden und die seit dem letzten Lauf 5 Minuten war vergangene Zeit ist, können Sie Angenommen, du bist gerade aus dem Schlaf aufgewacht? Dann brechen Sie den aktuellen Ajax-Anruf ab und starten ihn neu.

0

Die beste Antwort ist "Tu das nicht". Der Server wartet darauf, zu antworten, während er auf der Serverseite nach Änderungen sucht. Lassen Sie den Server antworten und lassen Sie den jQuery-Ping in einem Intervall ablaufen. Sie können lastchanged oder haschanged einschließen, wenn Sie verhindern möchten, dass die Aktualisierung tatsächlich stattfindet, wenn keine Statusänderung erfolgt. Wenn der Server jedoch die gleiche Arbeit leistet, lassen Sie ihn einfach antworten und warten Sie auf die nächste Abfrage.

setInterval(function() { 
    $.post({"/listen", version, function (data) { 
     if(data.haschanged) 
      version = handleUpdates(data); 
    }).fail(function() { 
     // any error correction on failed call 
    }); 
}, 1000);