2012-06-04 5 views
23

Auf einer meiner Skripte Ich habe diesen Code:Wie wird eine WebSockets-Verbindung zwischen Seiten aufrechterhalten?

var webSocket = window.WebSocket || window.MozWebSocket; 
window.ws = new webSocket('ws://64.121.210.140:2585/consoleappsample', 'my-protocol'); 

der gut arbeitet. Wenn der Benutzer jedoch Seiten wechselt, muss ich die Verbindung wiederherstellen. Ich glaube, das verursacht Probleme in meinem Code, denn wenn der Client Daten an den Server sendet und dann die Seiten wechselt, werden die Daten möglicherweise nicht empfangen und die Race-Bedingungen treten auf.

Ich habe versucht, die window.ws in globalen Geltungsbereich, aber es schien nicht das Problem zu beheben. Gibt es eine Möglichkeit, dass die WebSockets-Verbindung zwischen den Seiten bestehen bleibt, sodass die Verbindung nicht ständig wiederhergestellt werden muss?

+3

Ich glaube nicht. Ihre Anwendungslogik sollte jedoch Verbindungsprobleme abdecken. –

Antwort

19

Der von Ihnen erwähnte globale Bereich bezieht sich immer auf den JavaScript-Kontext, und für jedes Fenster wird ein Kontext erstellt (und zerstört, wenn das Dokument aus dem Speicher entladen wird). Daher ist Ihr Aufwand nutzlos: Sie können keine Verbindung geöffnet halten, wenn der Benutzer die Seite wechselt. Natürlich können Sie Ihre Webapp als "single page" -Anwendung haben, wo alle Daten mit XMLHttpRequest/ajax/WebSocket geladen werden. Wenn Sie die Seite verlassen, bedeutet dies, dass Sie die Anwendung verlassen/herunterfahren müssen und es sinnvoll ist, den Socket zu schließen.

Ein anderer alter Ansatz könnte sein, Ihre Seiten in einen Rahmen zu stellen, in dem der Benutzer nur im Rahmen navigiert (auch wenn es die gesamte Größe des Fensters einnimmt). Auf diese Weise können Sie Ihren WebSocket im obersten Fenster erstellen, das niemals geändert wird (das bedeutet auch, dass die in der Adressleiste angezeigte URL immer dieselbe ist).

Sagte, dass ich mit @dystoopy einverstanden: Ihre Anwendung sollte immer in der Lage sein, mit diesem Szenario umzugehen - der Benutzer könnte ein Netzwerkproblem haben und die Verbindung für einen Moment verloren, auch wenn es die Seite nicht verlässt.

+1

Gibt es mit dem Frame-Trick eine Möglichkeit, den Ort in der Adressleiste auf die navigierte Position innerhalb des Frames zu verweisen, der den navigierbaren Inhalt enthält? Automatisch? Bleiben die Links im Inhalt klar? – oberstet

+1

Sie können versuchen, etwas mit den [History APIs] (https://developer.mozilla.org/de/DOM/Manipulating_the_browser_history) zu tun. – ZER0

+1

Ich weiß, das ist eine alte Antwort, aber wenn eine Anwendung hat Benutzer immer die Seite wechseln, wird dies nicht den Web-Socket-Server mit konstanter trennt und verbindet erneut? – Alias

16

Sie könnten versuchen, Ihre WebSocket-Verbindung in einem Shared WebWorker zu erstellen, der es mehreren Seiten derselben Domäne ermöglicht, einen Ausführungskontext zu teilen. Es ist jedoch unklar, ob Shared Workers persistent über eine Seite neu zu laden oder zu ersetzen sind: Do Shared Web Workers persist across a single page reload, link navigation

Shared WebWorker haben derzeit limited browser support (Webkit und Opera) derzeit.

aktualisieren:

Da ein einziger gemeinsamen Web-Arbeiter mehr Seiten dienen können, ist die Implementierung etwas komplizierter, dass die normale Web-Arbeiter. Hier

ist ein gemeinsames Web-Arbeiter Beispiel, das WebSockets verwendet und teilt zwischen

Zuerst wird das HTML:

<!DOCTYPE html> 
<html> 
<body> 
<script> 
    var worker = new SharedWorker("shared.js"); 
    worker.port.addEventListener("message", function(e) { 
     console.log("Got message: " + e.data); 
    }, false); 
    worker.port.start(); 
    worker.port.postMessage("start"); 
</script> 
</body> 
</html> 

Die Javascript, die den freigegebenen Arbeiter in shared.js implementiert:

var ws = null 
var url = "ws://" + location.hostname + ":6080" 
self.addEventListener("connect", function(e) { 
    var port = e.ports[0] 
    port.addEventListener("message", function(e) { 
     if (e.data === "start") { 
      if (ws === null) { 
       ws = new WebSocket(url); 
       port.postMessage("started connection to " + url); 
      } else { 
       port.postMessage("reusing connection to " + url); 
      } 
     } 
    }, false); 
    port.start(); 
}, false); 

Ich habe überprüft, dass dies in Chrome 52 funktioniert.

+0

Ich habe Zweifel. In diesem Fall gibt es keine Websocket-Unterstützung in Webworkern. Wie können wir den Kontext der App beibehalten? –

+0

@kongaraju, Sie können WebSockets über Web Workers in Chrome verwenden, und es gibt einen Mozilla-Bug, um die Unterstützung dafür in Firefox zu implementieren: https://bugzilla.mozilla.org/show_bug.cgi?id=504553 – kanaka

+0

Wenn ich versuche zuzugreifen websockets über webworkers in chrom gibt es DOM ausnahme zurück. Können Sie ein Beispiel angeben? –

0

Leider ist die sauberste Lösung, ohne Ihren Standort in einer SPA-Anwendung zu ändern, mit nur einem ServiceWorker zu erreichen, da er den Job im Hintergrund erledigt (auch bei geschlossenem Tab) und auch Probleme mehrerer Tabs löst. Ich sagte "unglücklicherweise", weil sie immer noch nicht mit den meisten Browsern kompatibel sind. Die einzige Lösung, die ich selbst gefunden habe, besteht darin, Socket-Kanäle auf der Serverseite zu gruppieren und eine Warteschlange zu erstellen, um die Nachrichten zu speichern, die durch das Wechseln der Seite verloren gehen. In diesem Fall haben Sie virtuelle Kanäle.

Verwandte Themen