I am working with a WebSocket and trying to be able to send socket data at anytime from throughout my application. When I attempt to access the send command from within another function, I am receiving:
Uncaught InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable.
This only is occuring when I call a function, this is how I am setting up my websocket:
Main.socket = (function() {
var socket = new WebSocket("ws://server:port");
socket.onopen = function() {  
    console.log("Socket has been opened!");  
}
function send() {
    socket.send('test');
}
return {
    socket: socket,
    send: send
}
})();
I am able to call the function globally, and also when I console.log Main.socket from within a function it is able to see the socket. But when I call the send function I get that error.
Here is an alternative solution to waiting for the web socket connection to come online, replace your call to :
function send() {
    web_socket.send('test');
}
with this :
function send(msg) {
    wait_for_socket_connection(socket, function() {
        socket.send(msg);
    });
};
function wait_for_socket_connection(socket, callback){
    setTimeout(
        function(){
            if (socket.readyState === 1) {
                if(callback !== undefined){
                    callback();
                }
                return;
            } else {
                console.log("... waiting for web socket connection to come online");
                wait_for_socket_connection(socket,callback);
            }
        }, 5);
};
                        The problem is that the socket has not been opened yet. WebSocket.send cannot be used until the asynchronous onopen event occurs.
While using setTimeout (for a long enough duration) "should work", the correct way to deal with asynchronous JavaScript programming is to treat program flow as a sequence of dependent events.
In any case, here is a small example showing how to use a jQuery Deferred Object which (as of jQuery 1.8 isn't broken and honors the Promises/A contract):
Main.socket = (function($) {
   var socket = new WebSocket("ws://server:port");
   // Promise will be called with one argument, the "send" function for this
   // socket.
   var readyPromise = $.Deferred();
   socket.onopen = function() {
     console.log("Socket has been opened!");
     readyPromise.resolve(socket.send)
  }
  return readyPromise;
})(jQuery);
Then later, in the code that uses this little module:
Main.socket.then(function (send) {
   // This will only be called after `Promise.resolve` is called in the module
   // which will be called in the `WebSocket.onopen` callback.
   send("Hello world!");
})
// This code may or may not execute before the `then` function above
// depending upon the state the Promise/Deferred Object.
// However, we can get consistent program flow by using `then`-chaining
// of promises.
Of course you don't have to use Promises - callbacks will work just fine, although I prefer the unified contract/framework of Promises - and you can use whatever names or structure is most fitting.
Also, note that it might not be good to have a single WebSocket for the entire page lifecycle as this won't correctly handle disconnect and recovery scenarios.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With