javascript xmlhttprequest - Kann das Entlade-Event verwendet werden, um eine Ajax-Anfrage zuverlässig auszulösen?




tutorial jquery (5)

Ich brauche eine Methode, um Benutzer-Editiersitzungen zu überwachen, und eine der Lösungen, die ich überprüfe, wird mich haben, ein unload Ereignis zu verwenden, um eine Ajax-Anfrage zu senden, um den Server über das Ende der Editiersitzung zu informieren. (Siehe: Überwachen von Benutzersitzungen zur Vermeidung von Bearbeitungskonflikten )

Mein (ziemlich begrenztes) Lesen des unload Ereignisses weist darauf hin, dass die an diesen Handler angehängten Codes schnell ausgeführt werden müssen, und wird daher normalerweise zum Löschen von Objekten verwendet, um Speicherlecks zu verhindern.

Meine Frage ist, kann das zuverlässig genug für diesen Zweck arbeiten?

PS. Ich weiß über die Option async: false .


Answers

Wir haben einen Fall, wo wir das brauchten. Es ist eine Berichtsseite, die seriösen Speicher auf dem Server benötigt, also wollten wir sie sofort freigeben, sobald sie die Seite verlassen haben. Wir haben ein Frameset erstellt und dort den Unload-Handler hinzugefügt. Der zuverlässigste Weg war, den src eines Bildes auf das freigebende Skript zu setzen. Wir haben sowohl das Entladen als auch das On-Fore-Out-Laden für die Cross-Browser-Kompatibilität genutzt. Es funktionierte nicht in Web-Kit-Nightlies, aber das Management war damit einverstanden.

Das war jedoch nicht meine vorgeschlagene Lösung. Ich würde einen Herzschlagansatz verwenden, der mehr Arbeit erfordert, aber viel robuster ist.

Ihre Seite sollte periodische Heartbeat-Anfragen senden. Jede Anfrage legt den letzten Herzschlag von einer Seite fest. Sie benötigen dann einen Thread, der auf dem Server ausgeführt wird und Speicher löscht, wenn der letzte Heartbeat zu lange her war.

Dies löst nicht das Problem, die Seite für eine lange Zeit zu verlassen. Dazu benötigen Sie eine Überwachung für die Benutzeraktivität und verlassen diese Seite nach einem Zeitraum der Inaktivität (stellen Sie sicher, dass Sie mit dem Benutzer bestätigen)


Sie müssen Ihre eigenen Tests durchführen, ob Ihr spezielles Szenario mit der Zeit funktioniert, die Sie beim unload , aber die AJAX-Anfrage ist ziemlich schnell, da AJAX asynchron ist. Sie senden einfach die Anfrage und dann sind Sie fertig! (Vielleicht müssen Sie das soeben erstellte Anfrageobjekt löschen.)

Wenn Sie überprüfen möchten, ob die AJAX-Anfrage es geschafft hat, müssen Sie sich mehr Sorgen machen / die async:false Option verwenden (wie diese Diskussion zeigt). Aber nur senden ist eine schnelle Boom-and-you-re-done-Operation.


Diese Methode ist ziemlich zuverlässig, wenn Ihr Server schnell genug reagiert. Etwas, auf das man wirklich achten sollte. Wenn Sie den Browser schließen und eine AJAX-Anforderung beim Entladen senden, besteht eine sehr gute Chance, dass die Antwort nicht rechtzeitig vom Server zurückkommt, bevor das Fensterobjekt zerstört wird. Was in diesem Fall (zumindest mit IE) passiert, ist, dass es Ihr Verbindungsobjekt verwaist und es nicht korrekt beendet, bis das Verbindungstimeout erreicht wird. Wenn Ihr Server keine Verbindung Keep-Alive aktiviert hat, nachdem Sie 2 Fenster schließen (während noch ein anderes Fenster geöffnet ist), werden Sie keine offenen Verbindungen zum Server (für IE6-7, für IE8 - 6 Windows) haben und es wird Ihnen nicht möglich sein, Ihre Website zu öffnen, bis Ihr Verbindungstimeout erreicht wird.

Ich kam in eine Situation wie diese, bevor ich ein Popup-Fenster öffnete, das eine AJAX-Anfrage beim Entladen schickte, es war sehr zuverlässig, aber es wurde von der oben beschriebenen Ausgabe geplagt, und es dauerte wirklich lange, bis ich es verfolgte runter und verstehe, was vor sich geht. Danach, was ich getan habe, wurde sichergestellt, dass das Eröffnungsfenster den gleichen Code zum Aufruf des Servers hatte und bei jedem Entladen auf den Öffner überprüft und den Code dort ausgeführt hat, wenn er vorhanden war.

Es scheint, dass, wenn Sie das allerletzte Browserfenster schließen, IE die Verbindung ordnungsgemäß zerstört, aber wenn ein anderes Fenster geöffnet ist, wird es nicht funktionieren.

PS Und nur um die obige Antwort zu kommentieren, ist AJAX nicht wirklich asynchron. Zumindest JS-Implementierung ist es nicht. Nachdem Sie eine Anfrage gesendet haben, wartet Ihr JS-Code immer noch auf eine Antwort vom Server. Es wird nicht die Ausführung des Codes blockieren, aber da der Server eine Weile braucht, um zu antworten (oder lange genug, damit Windows das IE-Window-Objekt beenden kann), werden Sie wahrscheinlich und wahrscheinlich auf das oben beschriebene Problem stoßen.


Hast du versucht zu verwenden

var i = new Image(1,1); 
i.src='http://...'

Und nur ein leeres Bild vom Server zurückgeben. Ich denke, es sollte zuverlässig sein, Skript wird blockieren. BTW: schön Zeitstempel hinzuzufügen, um Caching zu verhindern.


Wie viele Leute im Thread bemerkt haben, wird der Server die Anfrage immer noch verarbeiten, nur weil die Anfrage auf der Client-Seite abgebrochen wird. Dies erzeugt eine unnötige Belastung für den Server, da es Arbeiten ausführt, auf die wir im Front-End nicht mehr hören.

Das Problem, das ich zu lösen versuchte (das andere auch dazu führen können), besteht darin, dass ich, wenn der Benutzer Informationen in ein Eingabefeld eingab, eine Anfrage nach einem Google Instant-Gefühl auslösen wollte.

Um unnötige Anfragen zu vermeiden und das Snappiness des Frontends beizubehalten, habe ich Folgendes getan:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

Dies sendet im Wesentlichen alle 150ms eine Anfrage (eine Variable, die Sie für Ihre eigenen Bedürfnisse anpassen können). Wenn Sie nicht genau xhrQueue , was genau hier passiert, loggen Sie xhrCount und xhrQueue vor dem if-Block in die Konsole ein.





javascript ajax events reliability