dimitris93
dimitris93

Reputation: 4273

Sending messages with Websockets

I have the following html/javascript code that uses websockets to communicate with a server. It seems like I can only send(message) only inside the onmessage() and onopen() functions. How can I send data outside of those functions ?

<!DOCTYPE HTML>
<html>
<head>
    <script type="text/javascript">
        function WebSocketTest() {
            if ("WebSocket" in window) {
                var ws = new WebSocket("ws://localhost:57252/");

                ws.onopen = function () {
                    ws.send("Hi, from the client."); // this works
                    alert("Connection opened...");
                };

                ws.onmessage = function (event) {
                        alert("Message received..." + event.data);
                };

                ws.onclose = function () {
                    alert("Connection closed...");
                };

                ws.send("Hi, from the client."); // doesn't work
                ws.send("Hi, from the client."); // doesn't work
            }
        }
    </script>
</head>
<body>

<div id="sse">
    <a href="javascript:WebSocketTest()">Run WebSocket</a>
</div>

</body>
</html>

Upvotes: 1

Views: 34815

Answers (3)

Reza
Reza

Reputation: 141

This is the html file of Sanic webserver websocket demo.

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket demo</title>
</head>
<body>
    <script>
        var ws = new WebSocket('ws://' + document.domain + ':' + location.port + '/feed'),
            messages = document.createElement('ul');
        ws.onmessage = function (event) {
            var messages = document.getElementsByTagName('ul')[0],
                message = document.createElement('li'),
                content = document.createTextNode('Received: ' + event.data);
            message.appendChild(content);
            messages.appendChild(message);
        };
        document.body.appendChild(messages);
        window.setInterval(function() {
            data = 'bye!'
            ws.send(data);
            var messages = document.getElementsByTagName('ul')[0],
                message = document.createElement('li'),
                content = document.createTextNode('Sent: ' + data);
            message.appendChild(content);
            messages.appendChild(message);
        }, 1000);
    </script>
</body>

Upvotes: 0

jeffjenx
jeffjenx

Reputation: 17457

You are probably experiencing a race condition where you try to perform a send command even though the socket may not have been opened yet. There's an important note on the MDN that describes this behavior:

As establishing a connection is asynchronous and prone to failure there is no guarantee that calling the send() method immediately after creating a WebSocket object will be successful.

You, essentially, are calling the send method immediately after creating a WebSocket.

If you move that logic to a function and call that function when you know the connection has been open, you might be fine. For example, try moving the code into a timeout or another function that can be manually triggered after you know the socket connection has been established:

function sendMyMessages() {
    ws.send("Hi, from the client.");
    ws.send("Hi, from the client.");
}

<button onclick="sendMyMessages()">Test</button>

Upvotes: 4

aaronofleonard
aaronofleonard

Reputation: 2576

Because onopen is an asynchronous event.

It's similar to doing this:

var value;
$.ajax({
   url: '/post/data',
   success: function(response) {
        value = response;
   }
});

alert(value);

What do we get in the alert? undefined.

The websocket works in a similar manner, you cannot send until the connection has finished opening. It opens asynchronously. Therefore, anytime you try to use send, you must ensure that the connection is already open. Right now, you are trying to synchronously use those send calls, before the connection is actually open.

Upvotes: 2

Related Questions