36

第 1 部分:预期行为?

我看到 Firefox 和 Chrome 之间与onclose被调用的处理程序有关的浏览器行为不一致。

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

在我看来,Firefox 在这里的行为可能是正确的:

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

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

即使它可能导致一些鬼鬼祟祟的代码/意外行为

任何人都可以确认预期的行为吗?

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

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

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

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

示例和视频

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

这是我演示问题的视频: http ://www.screenr.com/vHn8 (已经很晚了,忽略这两个错误:))

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

4

2 回答 2

8

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

如果从服务器接收到关闭消息,则 wasClean 属性将为真

如果您的库在没有检查 wasClean 属性的情况下自动重新连接,那么这可能会导致问题,因为它会在页面刷新时尝试重新建立连接。您应该考虑不为此使用该库并手动执行它,这应该不会很难,只需在 onclose 函数中调用 connect 并使用 if 语句确保 onclean 属性为真。或者为了更安全,在 onbeforeunload 中设置一个变量以防止任何新连接。

希望这可以帮助!

于 2013-06-18T15:57:37.570 回答
0

令人惊讶的是,这仍然是 2022 年的当前行为。您可以通过在 websocket 的 onclose 处理程序中添加控制台日志来简单地演示这一点,并在查看控制台时单击 Firefox 与 Chrome 中的链接(确保在网页之间保留控制台) :

ws.onclose = function(e) {
  printMsg('CLOSE')
  // ... my other code ...
}

Firefox 会显示“关闭”,而 Chrome 不会。

于 2022-01-29T06:30:08.523 回答