2012-11-16 119 views
10

我可以在websockets上从服务器发送和接收消息。我需要编写一个函数将数据发送到服务器,并等待来自服务器的响应,然后将其作为函数的结果返回。带Websockets的同步请求

发送:

ws.send('my_message_to_server'); 

接收(这是一个事件):

ws.bind('message', function(message) { 
console.log(message); 
}); 

我的功能:

function request(message){ 
ws.send(message); 
    //How wait for receive??? 
    return response; 
} 
+0

你不能做的东西异步同步功能。忙碌的等待是糟糕的,JavaScript不支持它。你为什么想要这样做?看看承诺。 – Bergi

+0

@Bergi其实你可以。看看下面的答案。只是创建一个简单的队列,没有在这个例子中等待:) –

+0

@RonanDejhero:不,你的功能不同步。它确实使用异步回调,因为每个套接字侦听器都需要。 – Bergi

回答

3

当您创建的WebSocket,你通常添加的onMessage回调函数到客户端从服务器接收数据时调用的套接字。

var socket = new WebSocket("ws://example.com:8000/websocketapp.php"); 
socket.onmessage = function(msg){ 
     alert('The server says: ' + msg); 
} 

该块,直到服务器响应是一个坏主意概念,因为它意味着脚本的执行将挂起,直到从服务器的应答进来的功能。当服务器繁忙,网络延迟高这可能需要几秒钟的时间。因此,最好使用回调函数(在发生事件时调用的函数)。

当你能保证你每次只向服务器发送一个请求,你可以改变socket.onmessage功能来处理该服务器响应,并作用于它的功能:

socket.onopen = function() { 
    socket.send("What's your name?"); 
    socket.onmessage = function(message) { 
     alert("The server says its name is " + message); 
     socket.send("What is the answer to life, the universe and everything?"); 
     socket.onmessage = function(msg){ 
      alert("The server says the answer is: " + msg); 
     } 
    } 
} 

(顺便说一句:在设置回复处理程序以提高可读性之前,我编写了请求,最好是以相反的方式执行:先设置回复处理程序然后发送请求,这对于不太可能的但不是不可能的如果服务器响应速度太快以至于尚未设置处理程序)。

但是,当你有多个并行请求,你需要找出服务器指向哪个请求时,你需要更好的东西。例如,您可以使用onmessage函数来标识消息,然后将每个消息转发给专门的消息处理函数。

+0

你可能是指'socket.send()'? – Christoph

+0

是的,我喜欢。谢谢,我纠正了这个错误。 – Philipp

+0

如果服务器在服务器端发生某些事情时将某些信息“推回”客户端,该怎么办?这段代码如何工作?它不会! –

2

你应该在WebSockets上使用某种RPC协议。我建议你看看WAMP这是一个WebSocket子协议,它增加了RPC和PUB/SUB语义。它包括一个客户端库,它通过给你一个基于承诺的API来在一定程度上抽象异步连接。

下面是一个例子:

var wsuri = "ws://localhost:9000"; 

ab.connect(wsuri, function (session) { 
    session.call("http://example.com/simple/calc#add", 23, 7).then(
     function (res) { 
      console.log("got result: " + res); 
     }, 
     function (error, desc) { 
      console.log("error: " + desc); 
     } 
    ); 
}); 

有许多服务器端实现的用于此的。

1

WebSocket就像TCP一样,它只是一个传输层。你需要的是在webSocket上运行一个协议。该协议负责为您创建消息之间的相关性。您可能想看看AMQP,它是实时异步消息的最广泛和最完整的开放协议。有关简单的AMQP客户端JS库,请参阅https://github.com/dansimpson/amqp-js

我不知道您使用的服务器类型,但AMQP将为您提供最大的灵活性,因为AMQP在很多平台上都有很多支持。还有简单的AMQP消息代理实现。如果你的服务器是Java,那么你会想看看JMS。在这种情况下,您将需要一个更加复杂而强大的JMS代理。

9

前段时间我在一些在线游戏中使用了一种简洁的方式,但是您还需要更改服务器端的东西!

1日做一个函数来发送数据

var socketQueueId = 0; 
var socketQueue = {}; 

function sendData(data, onReturnFunction){ 
    socketQueueId++; 
    if (typeof(returnFunc) == 'function'){ 
     // the 'i_' prefix is a good way to force string indices, believe me you'll want that in case your server side doesn't care and mixes both like PHP might do 
     socketQueue['i_'+socketQueueId] = onReturnFunction; 
    } 
    jsonData = JSON.stringify({'cmd_id':socketQueueId, 'json_data':data}); 
    try{ 
     webSocket.send(jsonData); 
     console.log('Sent'); 
    }catch(e){ 
     console.log('Sending failed ... .disconnected failed'); 
    } 
} 
在服务器端

然后,处理请求时,你应该送cmd_id回客户端的响应

webSocket.onmessage = function(e) { 

    try{ 
     data = JSON.parse(e.data); 
    }catch(er){ 
     console.log('socket parse error: '+e.data); 
    } 

    if (typeof(data['cmd_id']) != 'undefined' && typeof(socketQueue['i_'+data['cmd_id']]) == 'function'){ 
     execFunc = socketQueue['i_'+data['cmd_id']]; 
     execFunc(data['result']); 
     delete socketQueue['i_'+data['cmd_id']]; // to free up memory.. and it is IMPORTANT thanks Le Droid for the reminder 
     return; 
    }else{ 
     socketRecieveData(e.data); 
    } 
} 

和创建一个函数来处理所有其他类型的回报:

socketRecieveData(data){ 
    //whatever processing you might need 
} 

so now simp LY,如果你想发送一些数据服务器并等待响应你简单做,具体的数据:

sendData('man whats 1+1', function(data){console.log('server response:');console.log(data);}); 
+0

哇,真是个好主意!我花了一些时间来理解,但是将回调发送到服务器并将其回送给客户端非常出色。 – Benvorth

+1

我一直在寻找这个确切的解决方案太懒惰,无法重新发明轮子。非常优雅和灵活。 'i_'是可选的,因为字典也可以使用int。在execFunc调用释放内存后,可以添加以下内容: delete socketQueue ['i _'+ data ['cmd_id']]; –