2012-06-04 36 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即可,因爲它可以在後臺執行作業(也可以關閉選項卡),並且還可以解決多個選項卡的問題。我說「不幸」,因爲它們仍然與大多數瀏覽器不兼容。 我自己找到的唯一解決方案是在服務器端對插槽通道進行分組,並創建一個隊列以便通過更改頁面來保存丟失的消息。在這種情況下,你有一種虛擬頻道。