Why not one method to connect and send in websocket?
Asked Answered
E

2

1

I am new websocket and refering to the below Spring Websocket tutorial and it is working fine in my system. I am also using stomp.js and sockjs-0.3.4.js.

https://spring.io/guides/gs/messaging-stomp-websocket/

If the html and javascript has two distinct methods like below, it works.

function connect() {
    var socket = new SockJS('/app/hello');
    stompClient = Stomp.over(socket);            
    stompClient.connect({}, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function(greeting) {
            //showGreeting(greeting);
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

function sendName() {
    var name = document.getElementById('name').value;
    stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
}

If I write a single javascript function as given below, it does not work and get the error as Uncaught Error: INVALID_STATE_ERR.

function startAndSend() {
            connect();
            sendName();
        }

I want to know why it is not working. It may be dumb question, please help me in this regard. I provide below the complete html file. Is it always necessary to write html button for connect and send information to websocket as given in the Spring Websocket example ? Is it not possible to onClick of a button, it will connect and send information to websocket ? It seems to be a peculiar for me, I need your help.

<!DOCTYPE html>
<html>
<head>
<title>Hello WebSocket</title>
<script src="sockjs-0.3.4.js"></script>
<script src="stomp.js"></script>
<script type="text/javascript">
        var stompClient = null;

        function setConnected(connected) {
            document.getElementById('response').innerHTML = '';
        }

        function connect() {
            var socket = new SockJS('/app/hello');
            stompClient = Stomp.over(socket);            
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/greetings', function(greeting) {
                    //showGreeting(greeting);
                    showGreeting(JSON.parse(greeting.body).content);
                });
            });
        }

        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        function sendName() {
            var name = document.getElementById('name').value;
            stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
        }

        function showGreeting(message) {
            var response = document.getElementById('response');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            console.log(message);
            p.appendChild(document.createTextNode(message));
            response.appendChild(p);
        }


        //Does not work
        function startAndSend() {
            connect();
            sendName();
        }
    </script>

</head>
<body>
    <noscript>
        <h2 style="color: #ff0000">Seems your browser doesn't support
            Javascript! Websocket relies on Javascript being enabled. Please
            enable Javascript and reload this page!</h2>
    </noscript>
    <div>
        Stomp Over Websocket using Spring
        <div>
            <button id="connect" onclick="connect();">Connect</button>
            <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
            <button id="check" onclick="startAndSend();">StartAndSend</button>
        </div>
        <div id="conversationDiv">
            <label>What is your name?</label><input type="text" id="name" />
            <button id="sendName" onclick="sendName();">Send</button>
            <p id="response"></p>
        </div>

    </div>
</body>
</html>
Emarginate answered 31/7, 2016 at 15:18 Comment(0)
E
3

That is because stompClient.connect() method is asynchronous and when you call sendName() right after connect() connection is not established yet.

You are supposed to call sendName() in stompClient.connect() callback to be sure that connection is established by the time sendName() invokes.

For example:

function connect() {
    var socket = new SockJS('/app/hello');
    stompClient = Stomp.over(socket);            
    stompClient.connect({}, function(frame) {
        setConnected(true);
        sendName();
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function(greeting) {
            //showGreeting(greeting);
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}
Emanuelemanuela answered 31/7, 2016 at 16:14 Comment(2)
@OlegKurbatov this is what I was looking for from last 2 and 1/2 days, thaks a lot, I made same mistakeCyprinid
@OlegKurbatov you can post answer for here, I will accept itCyprinid
A
0

Without being familiar with Stomp (so just a wild guess): The actual stompClient.connect call takes a callback as the second argument. This indicates that this runs asynchronous. Your attempt at using the connection then fails because it is executed before the connection has actually been established. Try what happens when you put the call into the callback of the connect function.

Anaclitic answered 31/7, 2016 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.