1

I am trying to set up multiple websockets on a client side application in javascript. My websockets.js script is supposed to be connecting to a server's websocketserver and then assigning event emitters with corresponding functions.

Because I have multiple connecting objects on the same webpage, I thought I'd just make a function that uses 'this' a lot so that I can just write out:

    this.socket.onopen( function(){  
                message('<p class="event">Socket Status: 
                                '+this.socket.readyState+' 
                                (open)',this.chatString);  
                    }   );

The problem is that by the time an event gets triggered, the function has lost its scope. I get an error in this onopen callback that says 'cannot return property 'readyState' of "undefined".

When I consider how many websockets I've seen on the same webpage I realize I am obviously doing this quite wrong. Below is my websockets.js script. please feel free to point out my sheer violations of good coding practice with respect to websockets, I was just trying to test out websockets at first but am now really wondering how I'm supposed to employ multiple websockets on one page.

    // This is the JavaScript file for the basic LabVIEW WebSockets demo.
    // Copyright © 2016 by MediaMongrels Ltd. 

    $(document).ready(function() {  
        connect = function(num,ind){  

            debugger;
            var i = ind.toString();
            this.sendString = '#port'+i+'send';
            this.chatString = '#port'+i+'chat';

            this.host = "ws://localhost:"+num;
            debugger;
            // default uses 80, but this can be changed to any port. Change 'localhost' if connecting to a server running on another IP address.
            try
            {  
                this.socket = new WebSocket(this.host);

                message('<p class="event">Socket Status: '+this.socket.readyState +' (create)',this.chatString);
                // Tell the user the connection has been established
                this.socket.onopen = function(){  
                    message('<p class="event">Socket Status: '+connect.socket.readyState+' (open)',this.chatString);  
                }   
                // Display the received message
                this.socket.onmessage = function(msg){  
                    message('<p class="message">Received: '+msg.data,this.chatString);  
                }  
                // Tell the user the connection has been closed
                this.socket.onclose = function(){  
                    message('<p class="event">Socket Status: '+connect.socket.readyState+' (Closed)',this.chatString);  
                }           
            } 
            catch(exception){  
                message('<p>Error'+exception,this.chatString);  
            }  

            $(this.sendString).keypress(function(event) {  
                if (event.keyCode == '13') {  
                    send(this.sendString);  
                }  
            });     

            // Close the connection from the client side
            $('#port'+num+'disconnect').click(function(){  
                this.socket.close();  
            });

            $('#error').text('port '+i+' processed...');
        }

        function message(msg,ctrl){  
            $(ctrl).append(msg+'</p>');    
        } 

        function send(ctrl){
            var text = $(ctrl).text();  
            $(ctrl).text("");
            if(text==""){  
                message('<p class="warning">Please enter a message');  
                return;  
            } 

            try {  

                connect.socket.send(text);  
                message('<p class="event">Sent: '+text,ctrl.slice(0,6)+'chat')  

            } catch(exception){  
                message('<p class="warning">');  
            } 
        }
        $('#connect').click(function(){var request = new XMLHttpRequest();
            var uri = "socks/"+$('#username').val();
            request.open('GET', uri);
            request.responseType = 'text';
            request.send();
            request.onload = function() {
                if(!("WebSocket" in window))  
                    $('#error').text('Oh no, you need a browser that supports WebSockets.' +
                    'How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>');
                else{
                    s = request.response;
                    if(s!="error!"){
                        var arg = [];
                        for(var i = 0;i<3;i++){
                            if (i==2) 
                                arg[i]=s.slice(0);
                            else{
                                arg[i]=s.slice(0,s.indexOf(","));
                                s = s.slice(s.indexOf(',')+1);
                            }
                        }
                        // new connect(arg[1],2); new connect(arg[2],3); 
                        var connect1 = new connect(arg[0],1);
                        var connect2 = new connect(arg[1],2);
                        var connect3 = new connect(arg[2],3);
                    }
                    else $('#error').val("We couldn't find your username!<p> Please make sure its correct.");
                }
            }; 
        }); 
    });

2 Answers 2

1

You are losing context because your event handler is working asynchronously and have no connection to your class-function. You should bind it with this context.

this.socket.onopen = function(){
    message('<p class="event">Socket Status:' + connect.socket.readyState + ' (open)' , this.chatString);  
}.bind(this)

Apply this to other event handlers as well, for onmessage, onclose. So you will have no problems.

Sign up to request clarification or add additional context in comments.

8 Comments

do i have to add this. to the message() and send() functions as well?
As far as I can see, no. The thing to consider is: if you are using this, you should know what this points to. For asyn code, such as events or promises in javascript, this context is lost. Because that code runs when the event occurs. Therefore if you need to use this, bind a function as in the above example. Send and message does not use this.something
may I ask, what would the effect on its usage be if i did happen to apply this. to the message or send functions? I see that I don't have to do it, but if I do, then I can't call those functions without saying this.message or this.send.
what function(){}.bind(whatever) does is that it returns you a function with this bound to whatever. So in that function if you call alert(this) you will see a popup showing you contents of whatever. So doing bind(this) to every function does not change behavior for synchronous functions because their context is already there.
i get that, i was just wondering what this.message() would do. Is it that this.message(). I guess it's possible other objects might have a message function, is that how you would make a distinction between them?
|
0

Declare a local variable like this: Var that=this; this.socket.onopen( function(){
message('Socket Status:'+that.socket.readyState+'(open)',that.chatString);
} );

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.