【问题标题】:Should WebSocket.onclose be triggered by user navigation or refresh?WebSocket.onclose 应该由用户导航触发还是刷新触发?
【发布时间】:2012-06-13 12:13:00
【问题描述】:

第 1 部分:预期行为?

我发现 Firefox 和 Chrome 之间在调用 onclose 处理程序方面存在一些不一致的浏览器行为。

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

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

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

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

虽然可能会导致一些sneaky code/unexpected behaviour

谁能确认预期的行为?

第二部分:如何实现自动重连?

如果您有一个为用户自动重新连接的库,您如何知道是否应该尝试重新连接?你检查CloseEvent.wasClean 属性吗?我不得不假设“干净”意味着关闭应该通过对WebSocket.close() 的 API 调用或服务器发送关闭帧来发生?如果网络错误导致关闭,我猜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 连接关闭。但是,如果您仔细观察或亲自尝试,您会看到在页面刷新之前记录了关闭事件。

【问题讨论】:

标签: event-handling websocket reconnect


【解决方案1】:

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

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

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

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2012-06-24
    • 1970-01-01
    相关资源
    最近更新 更多