Синхронный запрос с веб-узлами

Я могу отправлять и получать сообщения с сервера на веб-сайтах. Мне нужно написать функцию, которая будет отправлять данные на сервер и ожидает ответа от сервера, а затем возвращает его в результате функции.

Send:

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;
}

Ответ 1

Там аккуратный способ, который я использовал в некоторых онлайн-играх некоторое время назад, но вам также нужно будет изменить материал на стороне сервера!

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
}

теперь просто, если вы хотите отправить некоторые данные для сервера и дождаться ответа на эти конкретные данные, которые вы просто делаете:

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

Ответ 2

Когда вы создаете websocket, вы обычно добавляете функцию обратного вызова onmessage в сокет, который вызывается всякий раз, когда клиент получает данные с сервера.

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

Функция, которая блокируется до тех пор, пока сервер не ответит, является плохой идеей концептуально, потому что это означает, что выполнение script будет зависать до тех пор, пока не войдет ответ с сервера. Когда сервер занят, а сетевая латентность высока, это может занять несколько секунд. По этой причине лучше работать с функциями обратного вызова (функции, вызываемые при возникновении события).

Если вы можете гарантировать, что вы отправляете только один запрос за раз на сервер, вы можете просто изменить функцию socket.onmessage на функцию, которая обрабатывает ответ сервера и действует на него:

 socket.onopen = function() {
    socket.send("What 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, которая идентифицирует сообщение, а затем пересылает каждое сообщение специализированной функции обработчика сообщений.

Ответ 3

Вы должны использовать какой-то протокол RPC поверх WebSockets. Я предлагаю вам взглянуть на 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);
        }
    );
});

Для этого существует ряд серверных реализаций.

Ответ 4

WebSocket похож на TCP, это просто транспортный уровень. Вам нужно запустить протокол поверх webSocket. Протокол заботится о создании корреляций между сообщениями для вас. Вы можете взглянуть на AMQP, который является самым обширным и полным открытым протоколом для асинхронных сообщений в режиме реального времени. См., Например, https://github.com/dansimpson/amqp-js для простой JS-библиотеки клиента AMQP.

Я не знаю, какой тип сервера вы используете, но AMQP предоставит вам максимальную гибкость, так как много поддержки AMQP на многих платформах. Существуют также простые реализации брокера сообщений AMQP. Если ваш сервер - Java, тогда вы захотите посмотреть JMS. в этом случае вам понадобится более сложный, но надежный брокер JMS.

Ответ 5

Я думаю, что проект WebSockets-Callback будет проще в использовании

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