¿Cómo mantener una conexión WebSockets entre páginas?

En uno de mis scripts tengo este código:

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

Lo cual funciona bien. Sin embargo, cuando el usuario cambia de página, tengo que volver a establecer la conexión. Creo que esto está causando problemas en mi código porque si el cliente envía datos al servidor y luego cambia de página, es posible que no se reciban los datos y se produzcan condiciones de carrera.

Traté de poner window.ws en el scope global, pero no pareció solucionar el problema. ¿Hay alguna forma de que la conexión WebSockets persista entre las páginas para que la conexión no tenga que restablecerse constantemente?

El scope global que mencionó está siempre relacionado con el contexto de JavaScript, y se crea un contexto para cada ventana (y se destruye cuando el documento se descarga de la memoria). Por lo tanto, su esfuerzo es inútil: no puede mantener una conexión abierta si el usuario cambia de página. Por supuesto, puede tener su aplicación web como aplicación de “página única”, donde se cargan todos los datos usando XMLHttpRequest / ajax / WebSocket. Entonces, abandonar la página significa dejar / cerrar la aplicación, y tiene sentido cerrar el socket.

Otro enfoque anterior podría poner sus páginas en un marco, donde el usuario navegue solo en el marco (incluso si toma el tamaño completo de la ventana). De esa manera, puede crear su WebSocket en la ventana superior, que nunca cambiará (eso también significa que la URL mostrada en la barra de ubicación siempre será la misma).

Dijo que estaba de acuerdo con @dystroy: su aplicación siempre debería ser capaz de manejar este escenario: el usuario podría tener algún problema de red y perder la conexión por un momento, incluso si no sale de la página.

Podría intentar crear su conexión WebSocket en un WebWorker Compartido que permita que varias páginas del mismo dominio compartan un contexto de ejecución. Sin embargo, no está claro si los trabajadores compartidos persisten en una página para volver a cargar o reemplazar: ¿los trabajadores web compartidos persisten en una sola página de recarga, enlace de navegación

Además, Shared WebWorkers tiene compatibilidad de navegador limitada (webkit y Opera) actualmente.

Actualización :

Dado que un solo trabajador web compartido puede servir para varias páginas, la implementación es un poco más complicada que la de los trabajadores normales de la web.

Aquí hay un ejemplo de trabajador web compartido que usa WebSockets y puede compartir entre

Primero el HTML:

       

El Javascript que implementa el trabajador compartido en shared.js :

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

He verificado que esto funciona en Chrome 52.

Desafortunadamente, la solución más limpia sin cambiar su sitio en una aplicación SPA se obtiene utilizando solo un ServiceWorker porque hace el trabajo en segundo plano (también con la pestaña cerrada) y también resuelve problemas de varias tabs. Dije “desafortunadamente” porque todavía no son compatibles con la mayoría de los navegadores. La única solución que he encontrado consiste en agrupar los canales de socket en el lado del servidor, y crear una cola para mantener los mensajes perdidos al cambiar de página. En este caso, tiene una especie de canales virtuales.