-
Notifications
You must be signed in to change notification settings - Fork 455
Always update connection state using _setState #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for highlighting this issue and proposing a solution! I agree that the inconsistency in events emitted when using A related but separate question is when constructing a ShareDB I'm inclined to maintain the current behavior, which is that no connection state events are emitted on construction. I think that instantiation triggering an event emission would be surprising. In addition, a typical use case for these events is showing a user a message to indicate that they are offline but the app is attempting to connect. Developers may or may not want to display the message on the initial connection, especially on page load. The preferred UX may be to show a connecting message only when the network unexpectedly had an issue and the client is attempting to reconnect for the user automatically. Emitting an event following construction would make this more complex to implement. This may mean that developers have to take care to handle the initial connection state of the socket they are passing in when they initially create a This means that the event sequence would typically be:
Or a repeated connection failure:
I'll add inline comments for suggestions on the potential code changes. Especially because this will change the behavior of the API in a subtle way, we'll also want to add unit tests before we merge this in. Started working on those with @rkstedman today: #188 |
lib/client/connection.js
Outdated
@@ -48,6 +48,8 @@ function Connection(socket) { | |||
|
|||
this.debug = false; | |||
|
|||
this.state = 'disconnected' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid emission on initial construction, I'd set this based on the state of the socket passed in:
this.state = connectionState(socket);
And add the function:
function connectionState(socket) {
if (socket.readyState === 0 || socket.readyState === 1) return 'connecting';
return 'disconnected';
}
lib/client/connection.js
Outdated
@@ -90,7 +92,7 @@ Connection.prototype.bindToSocket = function(socket) { | |||
// - 'disconnected' Connection is closed, but it will reconnect automatically | |||
// - 'closed' The connection was closed by the client, and will not reconnect | |||
// - 'stopped' The connection was closed by the server, and will not reconnect | |||
this.state = (socket.readyState === 0 || socket.readyState === 1) ? 'connecting' : 'disconnected'; | |||
this._setState((socket.readyState === 0 || socket.readyState === 1) ? 'connecting' : 'disconnected'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update this line to use the function:
var newState = connectionState(socket);
this._setState(newState);
1 similar comment
I agree with your arguments about the synchronous initial event and made the changes you requested. As a side note, I think that it does not affect the observable behaviour because since the initial event was synchronous, there was no way to attach a listener to catch it. I've also added some tests for the connection state. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Great contribution. Thanks so much! I'll merge and publish a new beta version.
@@ -90,4 +91,71 @@ describe('client connection', function() { | |||
}); | |||
}); | |||
|
|||
describe('state management using setSocket', function() { | |||
it('initial connection.state is connecting, if socket.readyState is CONNECTING', function () { | |||
// https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-connecting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the links to the spec! 🥇
describe('state management using setSocket', function() { | ||
it('initial connection.state is connecting, if socket.readyState is CONNECTING', function () { | ||
// https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-connecting | ||
var socket = { readyState: 0 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style-wise, we tend not to put spaces inside of brackets, and use semicolons. I'll just go ahead and clean up after merging.
Before this PR the connection event sequence could be like:
when using a plain
WebSocket
andbindToSocket
in a browser. If some kind of reconnecting socket were used (withoutbindToSocket
), you might get theconnecting
events, too.After this PR is merged, the
connecting
event would be emitted consistently regardless of the socket implementation, for example: