使用Websockets进行同步请求

时间:2012-11-16 12:53:19

标签: javascript jquery javascript-events websocket

我可以在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;
}

5 个答案:

答案 0 :(得分:14)

我刚才在一些在线游戏中使用过一种简洁的方式,但你也需要在服务器端更改内容!

1st发送数据发送功能

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
}

所以现在只需要为服务器发送一些数据并等待特定数据的响应就可以了:

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

答案 1 :(得分:4)

创建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函数来标识消息,然后将每条消息转发给专门的消息处理函数。

答案 2 :(得分:2)

您应该在WebSockets之上使用某种RPC协议。我建议你看看WAMP这是一个添加RPC和PUB / SUB语义的WebSocket子协议。它包括一个客户端库,它通过为您提供基于promise的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);
        }
    );
});

有许多服务器端实现。

答案 3 :(得分:2)

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

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

答案 4 :(得分:0)

我认为项目WebSockets-Callback易于使用

wscb.send({cmd: 'Hello server!'},
    function(response){
        //do something...
    }
)