WebSocket.onclose应该由用户导航或刷新触发吗?

时间:2012-06-10 01:09:40

标签: event-handling websocket reconnect

第1部分:预期的行为?

我发现Firefox和Chrome之间的浏览器行为与被调用的onclose处理程序有关。

如果Chrome由用户页面导航/刷新引起,则Chrome似乎不会触发onclose。但是,Firefox会触发onclose

在我看来,Firefox可能在这里表现正确:

  

当WebSocket连接关闭时,可能干净利落,用户代理必须创建一个使用CloseEvent接口的事件,事件名称为close,不起泡,不可取消,没有默认操作,其wasClean属性为如果连接干净则设置为true,否则为false,其code属性设置为WebSocket连接关闭代码,其reason属性设置为WebSocket连接关闭原因;并将任务排队以首先将readyState属性的值更改为CLOSED(3),然后在WebSocket对象上调度该事件。

来源:http://www.w3.org/TR/2011/WD-websockets-20110419/#closeWebSocket

即使它可以导致一些sneaky code/unexpected behaviour

有人可以确认预期的行为吗?

第2部分:如何实现自动重新连接?

如果您有一个为用户自动重新连接的库,您如何知道是否应该尝试重新连接?你检查CloseEvent.wasClean财产吗?我不得不假设'干净'意味着关闭应该通过对WebSocket.close()的API调用或发送关闭帧的服务器发生?如果网络错误导致关闭,我猜测wasClean将是false

在Pusher JavaScript库中,我们假设(onclose - > waiting - >连接)关闭应触发重新连接,除非我们处于关闭状态 - 开发人员已选择关闭连接。似乎socket.io客户端库做出了相同的假设。

基于此,由用户导航/刷新引起的Firefox onclose事件会触发不需要的重新连接,因为两个库都没有检查CloseEvent.wasClean属性。

示例和视频

以下是一个可用于演示不一致性的示例: http://jsbin.com/awonod/7

以下是我展示问题的视频: http://www.screenr.com/vHn8 (已经很晚了,忽略了几次失误:))

需要注意的一点是,我点击Escape键也可能导致WebSocket连接关闭。但是,如果您仔细观察或亲自尝试,您将在页面刷新之前看到关闭事件。

1 个答案:

答案 0 :(得分:5)

出乎意料的行为是由于Firefox和Chrome处理关闭Websocket的方式。刷新页面时,两个浏览器都会关闭连接,但Firefox会执行您的onclose代码,而chrome会关闭连接并直接跳过重新加载新页面。所以,是的,我证实了这种奇怪的行为 更奇怪的是,根据我的观察,在chrome中调用websocket.close()将立即关闭连接并调用onclose函数,而Firefox则等待从服务器返回关闭消息。

如果从服务器收到关闭消息,则wasClean属性为true 如果您的库是自动重新连接而不检查wasClean属性,那么这可能会导致问题,因为它会在页面刷新时尝试重新建立连接。您应该考虑不使用库并手动执行,它应该非常难,只需使用if语句调用onclose函数中的connect,确保onclean属性为true。或者更安全的是在onbeforeunload中设置一个变量来阻止任何新的连接。

希望这有帮助!