2012-11-24 85 views
23

我正在尝试实现WebSocket并使用回退来轮询。如果WebSocket连接成功,readyState变为1,但如果失败,则readyState为3,我应开始轮询。如何等待WebSocket的readyState更改

我想是这样的:

var socket = new WebSocket(url); 
socket.onmessage = onmsg; 
while (socket.readyState == 0) 
{ 
} 
if (socket.readyState != 1) 
{ 
    // fall back to polling 
    setInterval(poll, interval); 
} 

我期待socket.readyState异步更新,并让我立即读它。但是,当我运行这个时,我的浏览器冻结了(在放弃之前我将它打开了大约半分钟)。

我想也许有一个onreadyStateChanged事件,但我没有在MDN参考中看到一个事件。

我应该如何实施?显然一个空循环将无法工作,并且没有这个事件。

+0

呃...我可能会错过一些东西,但为什么不使用'socket.onopen'? – raina77ow

+0

@ raina77ow如果套接字从不打开,我不认为'socket.onopen'会触发。 –

+0

是的,但在这种情况下你的代码应该做什么?我想,“等待套接字开放”显然不是一个答案。 ) – raina77ow

回答

0

您的while循环可能会锁定您的线程。尝试使用:

setTimeout(function(){ 
    if(socket.readyState === 0) { 
     //do nothing 
    } else if (socket.readyState !=1) { 
     //fallback 
     setInterval(poll, interval); 
    } 
}, 50); 
+0

第一个'if'需要什么? – raina77ow

+0

如果我理解正确,'readyState'不会立即更新。这就是我使用循环的原因。 –

+0

老实说,我不知道,我假设与OP问题中的while循环相同。它当然可以被删除,除非OP需要做一些事情,而'socket.readyState === 0',我试图不留下任何假设。 – agryson

0

就像你定义的onmessage处理程序,您还可以定义一个onerror处理。这个将在连接失败时被调用。

var socket = new WebSocket(url); 
socket.onmessage = onmsg; 
socket.onerror = function(error) { 
    // connection failed - try polling 
} 
+0

我测试过了,它不会着火。 –

+0

我在我的应用程序中使用它,每当连接到服务器时出现错误,它都被称为非常可靠。你是否仍然在代码中忙碌?它可能让JS引擎太忙而无法执行错误处理。 – Philipp

+0

我注释了while循环,并用'onerror'做了一个快速测试。它没有运行。我很确定服务器没有立即关闭,因为'onopen'也没有运行。我认为,而不是发生错误,服务器拒绝连接。 –

20

下面是一个更详细的解释。首先,请检查特定的浏览器API,因为并非所有浏览器都将使用最新的RFC。你可以参考

你不想运行循环来经常检查readystate,这是额外的开销,你不需要。更好的方法是理解所有与现状变化相关的事件,然后适当地连线。它们如下:

onclose当WebSocket连接的readyState更改为CLOSED时,将调用一个事件侦听器。侦听器收到一个名为“close”的CloseEvent。

onerror发生错误时要调用的事件侦听器。这是一个名为“error”的简单事件。

onmessage从服务器收到消息时要调用的事件侦听器。侦听器接收一个名为“message”的MessageEvent。

onopen当WebSocket连接的readyState更改为OPEN时要调用的事件侦听器;这表示连接已准备好发送和接收数据。这个事件是一个简单的,名称为“open”的事件。

JS完全是事件驱动的,所以你需要连接所有这些事件并检查readystate,这样你就可以从WS切换到相应的轮询。

我建议你看一下Mozilla的参考,更容易比RFC文档阅读,它会给你的API的一个很好的概述,以及它是如何工作的:看https://developer.mozilla.org/en-US/docs/WebSockets/WebSockets_reference/WebSocket

不要忘记做如果您有失败并重复轮询重试,直到成功重新连接的回调被触发。

+0

“你可以咨询”...? (我知道这是旧的) – akauppi

+0

读这个,是有道理的,除了所有'on'事件都不会暴露关闭和连接。只有onopen,onclose和error事件。 我不想在关闭状态下向ws发送消息。 –

4

看待http://dev.w3.org/html5/websockets/

搜索“事件处理程序”,找到表。

的OnOpen - >打开
的onMessage - >消息
的onerror - >错误
的OnClose - >关闭

function update(e){ /*Do Something*/}; 
var ws = new WebSocket("ws://localhost:9999/"); 

ws.onmessage = update; 
+0

我upvoted,因为W3的链接是有用的。 – javadba

21

这很简单,它完美地工作......你可以添加条件大约最大时间,或尝试使其更强大的数量...

function sendMessage(msg){ 
    // Wait until the state of the socket is not ready and send the message when it is... 
    waitForSocketConnection(ws, function(){ 
     console.log("message sent!!!"); 
     ws.send(msg); 
    }); 
} 

// Make the function wait until the connection is made... 
function waitForSocketConnection(socket, callback){ 
    setTimeout(
     function() { 
      if (socket.readyState === 1) { 
       console.log("Connection is made") 
       if(callback != null){ 
        callback(); 
       } 
       return; 

      } else { 
       console.log("wait for connection...") 
       waitForSocketConnection(socket, callback); 
      } 

     }, 5); // wait 5 milisecond for the connection... 
} 
+0

这可能只是我缺少的东西,但是当我运行你的代码时,我得到一个错误,告诉我“回调不是函数”。为什么回调作为函数在if(callback!= null){callback(); }' –

+1

适当的解决方案是使用事件处理程序,根据[Axel的答案](http://stackoverflow.com/a/13590558/752843)。 – Richard

+0

对我来说,奇怪的是websockets是一种推技术,但是已经将readyState作为同步的非推送呼叫。 –

0

在我的用例中,如果连接失败,我想在屏幕上显示一个错误。

let $connectionError = document.getElementById("connection-error"); 

setTimeout(() => { 
    if (ws.readyState !== 1) { 
    $connectionError.classList.add("show"); 
    } 
}, 100); // ms 

注意,在Safari(9.1.2)没有error事件被炒鱿鱼 - 否则我会在错误处理程序都放在这一点。

0

我根本没有使用池。相反,我使用排队。 首先,我创造新的发送功能和队列:

var msgs = [] 
function send (msg) { 
    if (ws.readyState !== 1) { 
    msgs.push(msg) 
    } else { 
    ws.send(msg) 
    } 
} 

然后我需要阅读和发送当第一次建立连接:在这个例子中

function my_element_click() { 
    if (ws == null){ 
    ws = new WebSocket(websocket_url) 
    ws.onopen = function() { 
     while (msgs.length > 0) { 
     ws.send(msgs.pop()) 
     } 
    } 
    ws.onerror = function(error) { 
     // do sth on error 
    } 
    } 
    msg = {type: 'mymessage', data: my_element.value} 
    send(JSON.stringify(msg)) 
} 

WebSocket连接上第一只创建单击。通常,第二条消息开始直接发送。

相关问题