我想实现以下行为。假设客户端有一个按钮,它触发一个通过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事件的队列中。这将导致消息丢失。
我想避免这种情况,我将感谢任何想法,评论或建议。
我想你担心handshakcomplete会在test (== CONNECTING)和bind()发生之间触发,并且永远不会发送handshakcomplete的消息。
理论上,如果所有存在的是JS,这将是错误的,因为事件不会触发,直到当前代码完成。然而,在现实中,该事件可能在后台的另一个线程上生成,并且在我们达到稳定状态后,仅在前台运行。
答案是不将消息嵌入到握手事件处理程序中。我建议将消息添加到队列/数组中,并在onopen处理程序中处理该数组。onopen事件可以在我们执行时触发(进入队列),但它不会运行,直到我们达到稳定状态(所有消息都在队列/数组中)。