diff --git a/umap/static/umap/js/modules/sync/engine.js b/umap/static/umap/js/modules/sync/engine.js index 640ae5f4..bc640aa2 100644 --- a/umap/static/umap/js/modules/sync/engine.js +++ b/umap/static/umap/js/modules/sync/engine.js @@ -75,19 +75,20 @@ export class SyncEngine { this.reconnect() return } - this.start(response.token) + await this.start(response.token) } - start(authToken) { + async start(authToken) { const path = this._umap.urls.get('ws_sync', { map_id: this._umap.id }) const protocol = window.location.protocol === 'http:' ? 'ws:' : 'wss:' - this.transport = new WebSocketTransport( + this.transport = new WebSocketTransport(this) + await this.transport.connect( `${protocol}//${window.location.host}${path}`, authToken, - this, this.peerId, this._umap.properties.user?.name ) + this.onConnection() } stop() { @@ -108,11 +109,11 @@ export class SyncEngine { this.websocketConnected = false this.updaters.map.update({ key: 'numberOfConnectedPeers' }) - this._reconnectTimeout = setTimeout(() => { + this._reconnectTimeout = setTimeout(async () => { if (this._reconnectDelay < MAX_RECONNECT_DELAY) { this._reconnectDelay = this._reconnectDelay * RECONNECT_DELAY_FACTOR } - this.authenticate() + await this.authenticate() }, this._reconnectDelay) } upsert(subject, metadata, value) { diff --git a/umap/static/umap/js/modules/sync/websocket.js b/umap/static/umap/js/modules/sync/websocket.js index 5a18f880..ee51019a 100644 --- a/umap/static/umap/js/modules/sync/websocket.js +++ b/umap/static/umap/js/modules/sync/websocket.js @@ -3,53 +3,57 @@ const PING_INTERVAL = 30000 const FIRST_CONNECTION_TIMEOUT = 2000 export class WebSocketTransport { - constructor(webSocketURI, authToken, messagesReceiver, peerId, username) { + constructor(messagesReceiver) { this.receiver = messagesReceiver + } - this.websocket = new WebSocket(webSocketURI) + async connect(webSocketURI, authToken, peerId, username) { + return new Promise((resolve, reject) => { + this.websocket = new WebSocket(webSocketURI) - this.websocket.onopen = () => { - this.send('JoinRequest', { token: authToken, peer: peerId, username }) - this.receiver.onConnection() - } - this.websocket.addEventListener('message', this.onMessage.bind(this)) - this.websocket.onclose = () => { - console.log('websocket closed') - if (!this.receiver.closeRequested) { - console.log('Not requested, reconnecting...') - this.receiver.reconnect() + this.websocket.onopen = () => { + this.send('JoinRequest', { token: authToken, peer: peerId, username }) + resolve(this.websocket) } - } - - this.websocket.onerror = (error) => { - console.log('WS ERROR', error) - } - - this.ensureOpen = setInterval(() => { - if (this.websocket.readyState !== WebSocket.OPEN) { - this.websocket.close() - clearInterval(this.ensureOpen) + this.websocket.addEventListener('message', this.onMessage.bind(this)) + this.websocket.onclose = () => { + console.log('websocket closed') + if (!this.receiver.closeRequested) { + console.log('Not requested, reconnecting...') + this.receiver.reconnect() + } } - }, FIRST_CONNECTION_TIMEOUT) - // To ensure the connection is still alive, we send ping and expect pong back. - // Websocket provides a `ping` method to keep the connection alive, but it's - // unfortunately not possible to access it from the WebSocket object. - // See https://making.close.com/posts/reliable-websockets/ for more details. - this.pingInterval = setInterval(() => { - if (this.websocket.readyState === WebSocket.OPEN) { - console.log('sending ping') - this.websocket.send('ping') - this.pongReceived = false - setTimeout(() => { - if (!this.pongReceived) { - console.warn('No pong received, reconnecting...') - this.websocket.close() - clearInterval(this.pingInterval) - } - }, PONG_TIMEOUT) + this.websocket.onerror = (error) => { + console.log('WS ERROR', error) } - }, PING_INTERVAL) + + this.ensureOpen = setInterval(() => { + if (this.websocket.readyState !== WebSocket.OPEN) { + this.websocket.close() + clearInterval(this.ensureOpen) + } + }, FIRST_CONNECTION_TIMEOUT) + + // To ensure the connection is still alive, we send ping and expect pong back. + // Websocket provides a `ping` method to keep the connection alive, but it's + // unfortunately not possible to access it from the WebSocket object. + // See https://making.close.com/posts/reliable-websockets/ for more details. + this.pingInterval = setInterval(() => { + if (this.websocket.readyState === WebSocket.OPEN) { + console.log('sending ping') + this.websocket.send('ping') + this.pongReceived = false + setTimeout(() => { + if (!this.pongReceived) { + console.warn('No pong received, reconnecting...') + this.websocket.close() + clearInterval(this.pingInterval) + } + }, PONG_TIMEOUT) + } + }, PING_INTERVAL) + }) } onMessage(wsMessage) {