1

我想实现以下行为。假设客户端有一个按钮,它触发了一个通过 websocket 发送消息的函数。第一次调用此函数时,会创建一个 WebSocket 实例,然后在以后的调用中使用。

创建 WebSocket 实例是非阻塞的。构造函数立即返回一个 WebSocket 对象,在后台开始握手。成功的连接会触发 onopen 回调。

当第二个呼叫进来并且 websocket 仍在执行握手(例如,用户双击按钮)时,就会出现问题。当 websocket 完成握手时,所有的消息都需要排队发送。

以下代码使用 jQuery 和自定义事件来收集握手期间收到的所有消息。

var ws = null;

function sendMessage(message) {
    if (!ws) {
        ws = new WebSocket("ws://example.com");
        ws.onopen = function() {
            $(document).trigger('handshakeComplete');
        }
    }
    if (ws.readyState == WebSocket.CONNECTING) { // *
            $(document).bind('handshakeComplete', message, function(event) {
                ws.send(event.data);
            });
    } else if (ws.readyState == WebSocket.OPEN) {
        // use the persistent connection
        ws.send(message);
    }
}

星号行的条件可能被评估为真,并且在那一刻 websocket 进入 OPEN 状态,执行 onopen 回调,并且只有在此之后,当前消息才被添加到等待握手完成事件的队列中。这将导致消息丢失。

我想避免这种情况,如果有任何想法、意见或建议,我将不胜感激。

4

1 回答 1

0

我认为您担心握手完成可能会在测试(== 连接)和 bind() 发生之间触发,并且永远不会发送握手完成的消息。

从理论上讲,如果所有存在的都是 JS,那将是错误的,因为在当前代码完成之前事件不会触发。然而,实际上事件可能在后台的另一个线程上生成,并且只有在我们达到稳定状态后才会在前台运行。

答案是不要将消息嵌入到握手事件处理程序中。我建议将消息​​添加到队列/数组中,并在 onopen 处理程序中处理数组。onopen 事件可以在我们执行时触发(排队),但在我们达到稳定状态(所有消息都在队列/数组中)之前它不会运行。

于 2012-05-01T18:43:03.583 回答