Part 1: Expected behaviour?
I'm seeing some inconsistent browser behaviour between Firefox and Chrome in relation to the onclose
handler being called.
It seems that Chrome does not trigger an onclose
if it was caused by a user page navigation/refresh. However, Firefox does trigger the onclose
.
It seems to me that Firefox may be behaving correctly here:
When the WebSocket connection is closed, possibly cleanly, the user agent must create an event that uses the CloseEvent interface, with the event name close, which does not bubble, is not cancelable, has no default action, whose wasClean attribute is set to true if the connection closed cleanly and false otherwise, whose code attribute is set to the WebSocket connection close code, and whose reason attribute is set to the WebSocket connection close reason; and queue a task to first change the readyState attribute's value to CLOSED (3), and then dispatch the event at the WebSocket object.
Source: http://www.w3.org/TR/2011/WD-websockets-20110419/#closeWebSocket
Even though it can lead to some sneaky code/unexpected behaviour.
Can anybody confirm the expected behaviour?
Part 2: How to implement auto-reconnect?
If you have a library that auto-reconnects for the user how do you know if you should try to reconnect? Do you check the CloseEvent.wasClean
property? I'm having to assume that 'clean' means that the close was supposed to happen through either an API call to WebSocket.close()
or the server sending a close frame? If a network error causes the close I'm guessing the wasClean
would be false
?
In the Pusher JavaScript library we assumed (onclose -> waiting -> connecting) that a close should trigger a reconnect unless we are in a closing state - the developer has chosen to close the connection. It would appear that the socket.io client library makes the same assumption.
Based on this the Firefox onclose event caused by user navigation/refresh triggers an unwanted reconnection because neither library check the CloseEvent.wasClean
property.
Example and Video
Here's an example that you can use to demonstrate the inconsistency: http://jsbin.com/awonod/7
Here's a video of me demonstrating the problem: http://www.screenr.com/vHn8 (it's late, ignore the couple of slip-ups :))
One point to note is that my hitting the Escape key could also be causing the WebSocket connection to close. However, if you watch closely or try for yourself you will see the close event being logged just before the page refreshes.