@@ -124,6 +124,48 @@ const readMessage = (provider, buf, emitSynced) => {
124
124
return encoder
125
125
}
126
126
127
+ /**
128
+ * Outsource this function so that a new websocket connection is created immediately.
129
+ * I suspect that the `ws.onclose` event is not always fired if there are network issues.
130
+ *
131
+ * @param {WebsocketProvider } provider
132
+ * @param {WebSocket } ws
133
+ */
134
+ const closeWebsocketConnection = ( provider , ws ) => {
135
+ if ( ws === provider . ws ) {
136
+ provider . ws = null
137
+ ws . close ( )
138
+ provider . wsconnecting = false
139
+ if ( provider . wsconnected ) {
140
+ provider . wsconnected = false
141
+ provider . synced = false
142
+ // update awareness (all users except local left)
143
+ awarenessProtocol . removeAwarenessStates (
144
+ provider . awareness ,
145
+ Array . from ( provider . awareness . getStates ( ) . keys ( ) ) . filter ( ( client ) =>
146
+ client !== provider . doc . clientID
147
+ ) ,
148
+ provider
149
+ )
150
+ provider . emit ( 'status' , [ {
151
+ status : 'disconnected'
152
+ } ] )
153
+ } else {
154
+ provider . wsUnsuccessfulReconnects ++
155
+ }
156
+ // Start with no reconnect timeout and increase timeout by
157
+ // using exponential backoff starting with 100ms
158
+ setTimeout (
159
+ setupWS ,
160
+ math . min (
161
+ math . pow ( 2 , provider . wsUnsuccessfulReconnects ) * 100 ,
162
+ provider . maxBackoffTime
163
+ ) ,
164
+ provider
165
+ )
166
+ }
167
+ }
168
+
127
169
/**
128
170
* @param {WebsocketProvider } provider
129
171
*/
@@ -148,35 +190,7 @@ const setupWS = (provider) => {
148
190
}
149
191
websocket . onclose = ( event ) => {
150
192
provider . emit ( 'connection-close' , [ event , provider ] )
151
- provider . ws = null
152
- provider . wsconnecting = false
153
- if ( provider . wsconnected ) {
154
- provider . wsconnected = false
155
- provider . synced = false
156
- // update awareness (all users except local left)
157
- awarenessProtocol . removeAwarenessStates (
158
- provider . awareness ,
159
- Array . from ( provider . awareness . getStates ( ) . keys ( ) ) . filter ( ( client ) =>
160
- client !== provider . doc . clientID
161
- ) ,
162
- provider
163
- )
164
- provider . emit ( 'status' , [ {
165
- status : 'disconnected'
166
- } ] )
167
- } else {
168
- provider . wsUnsuccessfulReconnects ++
169
- }
170
- // Start with no reconnect timeout and increase timeout by
171
- // using exponential backoff starting with 100ms
172
- setTimeout (
173
- setupWS ,
174
- math . min (
175
- math . pow ( 2 , provider . wsUnsuccessfulReconnects ) * 100 ,
176
- provider . maxBackoffTime
177
- ) ,
178
- provider
179
- )
193
+ closeWebsocketConnection ( provider , websocket )
180
194
}
181
195
websocket . onopen = ( ) => {
182
196
provider . wsLastMessageReceived = time . getUnixTime ( )
@@ -377,7 +391,7 @@ export class WebsocketProvider extends Observable {
377
391
) {
378
392
// no message received in a long time - not even your own awareness
379
393
// updates (which are updated every 15 seconds)
380
- /** @type {WebSocket } */ ( this . ws ) . close ( )
394
+ closeWebsocketConnection ( this , /** @type {WebSocket } */ ( this . ws ) )
381
395
}
382
396
} , messageReconnectTimeout / 10 ) )
383
397
if ( connect ) {
@@ -484,7 +498,7 @@ export class WebsocketProvider extends Observable {
484
498
this . shouldConnect = false
485
499
this . disconnectBc ( )
486
500
if ( this . ws !== null ) {
487
- this . ws . close ( )
501
+ closeWebsocketConnection ( this , this . ws )
488
502
}
489
503
}
490
504
0 commit comments