我想实现以下行为。假设客户端有一个按钮,它触发一个通过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);
}
}
有可能将星号行的条件评估为true,并且在那一刻,websocket在OPEN状态下传递,onopen回调被执行,并且只有在此之后,当前消息被添加到队列中等待handshakeComplete事件。这会导致消息丢失。
我想避免这种情况,我将不胜感激任何想法,意见或建议。
答案 0 :(得分:0)
我认为你担心握手完成可能会在测试(== CONNECTING)和bind()发生之间触发,而且握手完成的消息永远不会被发送。
理论上如果所有存在的都是JS,这将是错误的,因为事件在当前代码完成之前不会触发。但是,实际上事件可能在后台的另一个线程上生成,并且在我们达到稳定状态后仅在前台运行。
答案是不将信息嵌入握手事件处理程序中。我建议将消息添加到队列/数组中,并在onopen处理程序中处理数组。 onopen事件可以在我们执行时触发(排队等待),但是在我们达到稳定状态(所有消息都在队列/数组中)之前它不会运行。