使用Websockets进行同步请求

Art*_*yan 16 javascript jquery websocket

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

发送:

ws.send('my_message_to_server');
Run Code Online (Sandbox Code Playgroud)

接收(这是一个事件):

ws.bind('message', function(message) {
console.log(message);
});
Run Code Online (Sandbox Code Playgroud)

我的功能:

function request(message){
ws.send(message);
    //How wait for receive???
    return response;
}
Run Code Online (Sandbox Code Playgroud)

Ron*_*ero 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');
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在服务器端,在处理请求时,您应该使用响应将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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

socketRecieveData(data){
    //whatever processing you might need
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我正在寻找这个确切的解决方案,因为懒得重新发明轮子。非常优雅和灵活。'i_' 是可选的,因为字典也可以与 int 一起使用。您可以在 execFunc 调用后添加以下内容以释放内存: delete socketQueue['i_'+data['cmd_id']]; (2认同)

Phi*_*ipp 3

创建 websocket 时,通常会向套接字添加一个 onmessage 回调函数,每当客户端从服务器接收数据时就会调用该函数。

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

从概念上讲,阻塞直到服务器响应的函数是一个坏主意,因为这意味着脚本执行将挂起,直到服务器响应为止。当服务器繁忙且网络延迟很高时,这可能需要几秒钟。因此,最好使用回调函数(事件发生时调用的函数)。

当您可以保证一次只向服务器发送一个请求时,您可以将 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);
        }
     }
 }
Run Code Online (Sandbox Code Playgroud)

(顺便说一句:为了更好的可读性,我在设置回复处理程序之前编写了请求。最好以相反的方式进行:先设置回复处理程序,然后发送请求。这对于不太可能但并非不可能的情况很重要服务器响应速度太快以至于处理程序尚未设置的情况)。

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

  • 我的意思是,您向服务器发送一些数据,服务器响应时间太长(某些非常长的操作)并且您需要结果,但同时您向服务器发送另一个请求(并且也需要结果),然后服务器为您的第二个请求发送回复,一段时间后它完成了漫长的操作并将结果发送回给您,您将如何识别哪个响应哪个请求?你的例子基本上连接,发送数据并等待响应,如果你为每个请求打开一个连接那么websocks有什么用?你可以使用ajax代替 (2认同)