diff options
| author | Shulhan <ms@kilabit.info> | 2024-09-15 14:32:48 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2024-09-15 14:32:48 +0700 |
| commit | d1e96e09438b4a5c7580b86c469e817a61be991f (patch) | |
| tree | 4d81fb2fd62207bbb9162b81083c721ec8fd8e29 /websocket_client.js | |
| parent | 1cc9c9dd68a3a59c685505228336430624608852 (diff) | |
| download | pakakeh.ts-d1e96e09438b4a5c7580b86c469e817a61be991f.tar.xz | |
all: commit all generate JavaScript files
This is to simplify development on third party where they can
clone and include the file directly without installing or running
anything to build the files.
Diffstat (limited to 'websocket_client.js')
| -rw-r--r-- | websocket_client.js | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/websocket_client.js b/websocket_client.js new file mode 100644 index 0000000..3cfd1c7 --- /dev/null +++ b/websocket_client.js @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: 2021 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: GPL-3.0-or-later +const AUTO_RECONNECT_INTERVAL = 5000; +export class WuiWebSocketClient { + constructor(opts) { + this.opts = opts; + this.requestQueue = []; + this.reconnect_id = 0; + this.isOpen = false; + this.error = ""; + this.address = opts.address; + if (opts.auto_reconnect) { + if (opts.auto_reconnect_interval <= 0) { + opts.auto_reconnect_interval = AUTO_RECONNECT_INTERVAL; + } + } + this.connect(); + } + // + // Send the request and wait for response similar to HTTP + // request-response. + // + async Send(req) { + return new Promise((resolve) => { + const wuiRes = { + code: 0, + message: "", + }; + const reqQueue = { + req: req, + cbSuccess: (res) => { + wuiRes.code = res.code; + wuiRes.message = res.message; + if (res.code === 200 && res.body.length > 0) { + wuiRes.data = JSON.parse(atob(res.body)); + } + resolve(wuiRes); + }, + cbFail: (err) => { + wuiRes.code = 500; + wuiRes.message = err; + resolve(wuiRes); + }, + }; + this.requestQueue.push(reqQueue); + this.conn.send(JSON.stringify(req)); + }); + } + connect() { + this.conn = new WebSocket(this.address); + this.conn.onclose = () => { + this.onClose(); + }; + this.conn.onerror = () => { + this.onError(); + }; + this.conn.onmessage = (ev) => { + this.onMessage(ev); + }; + this.conn.onopen = () => { + this.onOpen(); + }; + } + // onClose handle connection closed by cleaning up the request + // queue. + onClose() { + this.requestQueue.forEach((reqq) => { + reqq.cbFail("connection closed"); + }); + this.isOpen = false; + this.error = "connection is closed by server"; + if (this.opts.auto_reconnect && !this.reconnect_id) { + this.reconnect_id = setInterval(() => { + this.connect(); + }, this.opts.auto_reconnect_interval); + } + if (this.opts.onDisconnected) { + this.opts.onDisconnected(); + } + } + onError() { + if (this.opts.onError) { + this.opts.onError(); + } + } + onMessage(ev) { + const res = JSON.parse(ev.data); + this.requestQueue.forEach((reqq, x) => { + if (reqq.req.id === res.id) { + reqq.cbSuccess(res); + this.requestQueue.splice(x, 1); + return; + } + }); + if (this.opts.onBroadcast && res.id == 0) { + this.opts.onBroadcast(res); + } + } + onOpen() { + this.isOpen = true; + this.error = ""; + if (this.reconnect_id) { + clearInterval(this.reconnect_id); + this.reconnect_id = 0; + } + if (this.opts.onConnected) { + this.opts.onConnected(); + } + } +} |
