From f30685d9c235c8a8a019da0fa1abdbf835494db9 Mon Sep 17 00:00:00 2001 From: Bogdan Bodnar Date: Wed, 4 Dec 2019 17:05:56 +0100 Subject: [PATCH] Add WS unsubscribtion. Code review improvements. --- src/webSockets/WebSockets.js | 41 ++++++++++++++++++++++++++++++------ src/webSockets/hooks.js | 19 ++++++++++++----- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/webSockets/WebSockets.js b/src/webSockets/WebSockets.js index 6fb9c50..c01407f 100644 --- a/src/webSockets/WebSockets.js +++ b/src/webSockets/WebSockets.js @@ -61,9 +61,36 @@ export class WebSockets { return this; } - subscribe(params) { + subscribe(module) { this.waitForConnection(() => { - this.send("subscribe", params); + this.send("subscribe", module); + }); + return this; + } + + unbind(module, action, callback) { + const callbacks = this.callbacks[module][action]; + + const index = callbacks.indexOf(callback); + if (index !== -1) { + callbacks.splice(index, 1); + } + + if (callbacks.length === 0) { + delete this.callbacks[module][action]; + } + + if (Object.keys(this.callbacks[module]).length === 0) { + this.unsubscribe(module); + } + + return this; + } + + unsubscribe(module) { + this.waitForConnection(() => { + this.send("unsubscribe", module); + delete this.callbacks[module]; }); return this; } @@ -82,15 +109,15 @@ export class WebSockets { let chain; try { chain = this.callbacks[json.module][json.action]; - } catch (e) { - if (e instanceof TypeError) { - console.log(`Callback for this message wasn't found:${e.data}`); - } else throw e; + } catch (error) { + if (error instanceof TypeError) { + console.log(`Callback for this message wasn't found:${error.data}`); + } else throw error; } if (typeof chain === "undefined") return; - for (let i = 0; i < chain.length; i++) chain[i](json); + chain.forEach((callback) => callback(json)); } close() { diff --git a/src/webSockets/hooks.js b/src/webSockets/hooks.js index 3ca0084..7c0fc61 100644 --- a/src/webSockets/hooks.js +++ b/src/webSockets/hooks.js @@ -11,12 +11,21 @@ export function useWSForisModule(ws, module, action = "update_settings") { const [data, setData] = useState(null); useEffect(() => { - if (ws && module) { - ws.subscribe(module) - .bind(module, action, (msg) => { - setData(msg.data); - }); + // Sometime we want to disable this hook if WS is not passed. We can't make conditional + // hooks, but we can disable it here. It's used especially in ForisForm when a module + // doesn't present any WS endpoint. + if (!ws) return; + + function callback(msg) { + setData(msg.data); } + + ws.subscribe(module) + .bind(module, action, callback); + + return () => { + ws.unbind(module, action, callback); + }; }, [action, module, ws]); return [data];