Javascript:正确地全球化Websocket发送函数

Javascript:正确地全球化Websocket发送函数,javascript,websocket,Javascript,Websocket,我正在使用WebSocket,并试图在整个应用程序中随时发送套接字数据。当我试图从另一个函数中访问send命令时,我收到: Uncaught InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. 这仅在我调用函数时发生,这是我设置websocket的方式: Main.socket = (function() { var socket = new WebSocke

我正在使用WebSocket,并试图在整个应用程序中随时发送套接字数据。当我试图从另一个函数中访问send命令时,我收到:

Uncaught InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable.
这仅在我调用函数时发生,这是我设置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
}
})();

我能够全局调用函数,并且当我从函数中调用console.log Main.socket时,它也能够看到套接字。但是当我调用send函数时,我得到了这个错误。

问题是套接字尚未打开
WebSocket.send
在异步
onopen
事件发生之前无法使用

当使用
setTimeout
(持续足够长的时间)“应该工作”时,处理异步JavaScript编程的正确方法是将程序流视为一系列依赖事件

在任何情况下,下面是一个小示例,展示了如何使用一个(从jQuery 1.8开始,它没有被破坏并遵守合同):

然后,在使用这个小模块的代码中:

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.
当然,您不必使用承诺-回调将很好地工作,尽管我更喜欢承诺的统一契约/框架-并且您可以使用任何最合适的名称或结构


另外,请注意,在整个页面生命周期中使用一个WebSocket可能不太好,因为这无法正确处理断开连接和恢复情况。

这里有一个替代解决方案,用于等待web socket连接联机,替换您的呼叫:

function send() {
    web_socket.send('test');
}
为此:

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);
};

我怀疑这是因为套接字尚未打开-是否调用了
onopen
?“试图使用不可用或不再可用的[Socket]对象[因为它处于无效状态]。”如果我打开控制台并执行Main.Socket.send('test'),则套接字已打开;我可以在我的服务器上看到这一点,但当我尝试从函数内部调用时,它失败了。我已经在我的主套接字中添加了一个init函数,我在开始时调用它。如果打开主控制台并调用Main.socket.send,时间已经过了——而且时间足够长,套接字可能有足够的时间打开(同样重要的是,JavaScript代码一直处于空闲状态,因此事件已经被处理)。从失败的代码中尝试此操作:在
setTimeout(函数(){Main.socket.send(“yay”)},500)
中调用
send
。当然,这是一个愚蠢的等待时间,实际上我们应该只等待直到触发打开。使用futures可以简化这种链接,但它需要在消费者中异步使用。啊!这就成功了,所以我想我将编辑Main.init以获得延迟,以便websocket有时间连接。谢谢不,不,那只是一个丑陋的黑客。利用onopen回调并公开您自己的异步绑定。如果您使用的是jQuery1.8+,它可以创建一个Promise/a对象。
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);
};