2012-06-04 39 views
23

在我的一个脚本,我有这样的代码:如何维护页面之间的WebSockets连接?

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

工作正常。但是,当用户更改页面时,我必须重新建立连接。我相信这会导致我的代码出现问题,因为如果客户端将数据发送到服务器,然后更改页面,则可能无法接收数据并且竞争条件正在发生。

我试图把window.ws放在全局范围内,但它似乎没有解决问题。有没有什么办法让WebSockets连接在页面之间持续存在,因此连接不需要不断重新建立?

+3

我不这么认为。但是您的应用程序逻辑应该涵盖连接问题 –

回答

19

您提到的全局范围始终与JavaScript上下文相关,并且会为每个窗口创建一个上下文(并在文档从内存中卸载时销毁)。因此,您的努力是无用的:如果用户更改页面,则无法保持连接打开。 当然,您可以将您的webapp作为“单页面”应用程序,其中所有数据都使用XMLHttpRequest/ajax/WebSocket加载。所以,离开页面意味着离开/关闭应用程序,并且合理地关闭套接字。

另一种老方法可以把你的页面放在一个框架中,用户只在框架中导航(即使它需要整个窗口的大小)。通过这种方式,您可以在最上方的窗口中创建WebSocket,这个窗口永远不会更改(这也意味着地址栏中显示的URL将始终保持不变)。

说,我同意@dystroy:你的应用程序应该总是能够处理这种情况 - 用户可能有一些网络问题,并暂时失去了连接,即使它不离开页面。

+1

使用框架技巧,是否有任何方法让地址栏中的位置反映包含可导航内容的框架内的导航位置?自动?随着内容中的链接保持简单的hrefs? – oberstet

+1

您可以尝试使用[历史API](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history)进行操作。 – ZER0

+1

我知道这是一个旧的回复,但如果一个应用程序有用户总是改变页面,这不会锤击网络套接字服务器与不断断开连接和重新连接? – Alias

16

您可以尝试在Shared WebWorker中创建WebSocket连接,该连接允许来自同一个域的多个页面共享执行上下文。但是,目前还不清楚共享工作者是否在整个页面上持续重新加载或替换:Do Shared Web Workers persist across a single page reload, link navigation

另外,共享Web工作人员目前有limited browser support(webkit和Opera)。

更新

由于单个共享网络工作者可以用于多个页面,执行要稍微复杂一些,正常的网络工作者。

下面是一个使用的WebSockets和可之间共享的共享网络工作者例如

首先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> 

实现在shared.js共享工人的使用Javascript:

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

我已经证实,这在Chrome 52中有效。

+0

我有疑问。在这种情况下,webworkers中没有websocket支持,我们如何维护应用程序的上下文。 –

+0

@kongaraju,你可以通过Web Workers在Chrome中使用WebSockets,Mozilla的bug在Firefox中实现对此的支持:https://bugzilla.mozilla.org/show_bug.cgi?id=504553 – kanaka

+0

当我尝试访问通过webworkers在Chrome中的websockets它返回DOM异常。你能指定一个例子吗? –

0

不幸的是,无需在SPA应用程序中更改您的网站就可以获得最干净的解决方案,只需使用一个ServiceWorker即可,因为它可以在后台执行作业(也可以关闭选项卡),并且还可以解决多个选项卡的问题。我说“不幸”,因为它们仍然与大多数浏览器不兼容。 我自己找到的唯一解决方案是在服务器端对插槽通道进行分组,并创建一个队列以便通过更改页面来保存丢失的消息。在这种情况下,你有一种虚拟频道。