I can send and receive messages from server on websockets. I need to write a function that will send data to the server and is awaiting a response from the server and then r
You should use some sort of RPC protocol on top of WebSockets. I suggest you take a look at WAMP which is a WebSocket sub-protocol that adds RPC and PUB/SUB semantics. It includes a client library which abstracts the async connection to some extent by giving you a promise based API.
Here is an example:
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);
}
);
});
There are a number of server-side implementations for this.
WebSocket is like TCP, it's just a transport layer. What you need is to run a protocol on top of webSocket. The protocol takes care of creating the correlations between messages for you. You may want to take a look at AMQP, which is the most extensive and complete open protocol for real time asynchronous messaging. See for example https://github.com/dansimpson/amqp-js for a simple AMQP client JS library.
I don't know what type of server you are using, but AMQP will give you the most flexibility as there is a lot of support for AMQP across many platforms. There are also simple AMQP message broker implementations. If your server is Java, then you will want to look at JMS. in which case you will need a more elaborate but robust JMS broker.
When you create a websocket, you usually add a onmessage callback function to the socket which is called whenever the client receives data from the server.
var socket = new WebSocket("ws://example.com:8000/websocketapp.php");
socket.onmessage = function(msg){
alert('The server says: ' + msg);
}
A function which blocks until the server responds is a bad idea conceptually, because it means that the script execution will hang until the answer from the server came in. When the server is busy and the network latency is high, this can take several seconds. For that reason it is better to work with callback functions (functions which are called when an event happens).
When you can guarantee that you only send one request at a time to the server, you can just change the socket.onmessage function to a function which processes the servers response and acts on it:
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);
}
}
}
(By the way: I wrote the request before setting the reply handler for better readability. It would be better to do it the other way around: set the reply handler first and then send the request. This is important for the unlikely but not impossible case that the server responds so fast that the handler wasn't set up yet).
But when you have multiple parallel requests and you need to find out which request the server is referring to, you will need something better. You could, for example, have an onmessage function which identifies the message and then forwards each message to a specialized message handler function.
I think the project WebSockets-Callback would be easier to use
wscb.send({cmd: 'Hello server!'},
function(response){
//do something...
}
)
There's a neat way I used in some online game a while ago, but you will need to change stuff on the server side as well !
1st make a function to send the data
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');
}
}
Then in the server side, when processing the request, you should send the cmd_id back to the client with the response
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);
}
}
and create a function to handle all other types of returns:
socketRecieveData(data){
//whatever processing you might need
}
so now simply if you want to send some data for the server and wait for response for that specific data you simple do:
sendData('man whats 1+1', function(data){console.log('server response:');console.log(data);});