From 0b15939f90a10f36fbcc3be15c6a1fea8f9dd628 Mon Sep 17 00:00:00 2001 From: Oliver Giles Date: Sat, 30 Jun 2018 20:19:41 +0300 Subject: [PATCH] resolves #59: pagination doesn't work after reconnect A subtle tweak to the websocket logic needed to handle this edge case. Better comments added. --- src/resources/js/app.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/resources/js/app.js b/src/resources/js/app.js index d8d14a4..8b18cdc 100644 --- a/src/resources/js/app.js +++ b/src/resources/js/app.js @@ -21,10 +21,15 @@ const WebsocketHandler = function() { // "status" is the first message the websocket always delivers. // Use this to confirm the navigation. The component is not // created until next() is called, so creating a reference - // for other message types must be deferred. Also check that - // the reference is not already created, this allows a subsequent - // status message to be handled as an update. - if (msg.type === 'status' && !this.comp) { + // for other message types must be deferred. There are some extra + // subtle checks here. If this websocket already has a component, + // then this is not the first time the status message has been + // received. If the frontend requests an update, the status message + // should not be handled here, but treated the same as any other + // message. An exception is if the connection has been lost - in + // that case we should treat this as a "first-time" status message. + // this.comp.ws is used as a proxy for this. + if (msg.type === 'status' && (!this.comp || !this.comp.ws)) { next(comp => { // Set up bidirectional reference // 1. needed to reference the component for other msg types @@ -44,7 +49,6 @@ const WebsocketHandler = function() { if (!this.comp) return console.error("Page component was undefined"); else { - this.comp.$root.connected = true; this.comp.$root.showNotify(msg.type, msg.data); if(typeof this.comp[msg.type] === 'function') this.comp[msg.type](msg.data); @@ -56,11 +60,17 @@ const WebsocketHandler = function() { // and a re-connection isn't meaningful if(!ev.wasClean && 'comp' in this) { this.comp.$root.connected = false; + // remove the reference to the websocket from the component. + // This not only cleans up an unneeded reference but ensures a + // status message on reconnection is treated as "first-time" + delete this.comp.ws; this.reconnectTimeout = setTimeout(()=>{ var newWs = setupWebsocket(path, (fn) => { fn(this.comp); }); - // pass on the current component for the cases where the - // connection fails (onclose is called again) before the - // status message can reassign the current component + // the next() callback won't happen if the server is still + // unreachable. Save the reference to the last component + // here so we can recover if/when it does return. This means + // passing this.comp in the next() callback above is redundant + // but necessary to keep the same implementation. newWs.comp = this.comp; }, 2000); }