add SmartWebSocket.js and documentation
This commit is contained in:
parent
af963b4c81
commit
fc082c45e8
37
README.md
37
README.md
|
@ -1 +1,38 @@
|
||||||
# Smart WebSocket
|
# Smart WebSocket
|
||||||
|
|
||||||
|
```js
|
||||||
|
// constructor(socketAddress, options = [], autoReconnect = true, debugName = null)
|
||||||
|
let socket = SmartWebSocket("ws://127.0.0.1:8080", [], true, "sock");
|
||||||
|
|
||||||
|
// close if connection is open, then re-open connection
|
||||||
|
socket.reconnect()
|
||||||
|
|
||||||
|
// close socket and disable auto-reconnect
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
// is socket connection open
|
||||||
|
if (socket.isReady()) {
|
||||||
|
|
||||||
|
// sends
|
||||||
|
// {"event" : "myEvent", "data" : { "abc" : "def" }}
|
||||||
|
// to server
|
||||||
|
// data is stringified using JSON before sending
|
||||||
|
socket.send("myEvent", { "abc" : "def"});
|
||||||
|
|
||||||
|
// sends
|
||||||
|
// abcdef
|
||||||
|
// to server. Same as calling socket.send on a regular WebSocket
|
||||||
|
socket.sendRaw("abcdef");
|
||||||
|
}
|
||||||
|
|
||||||
|
// is called when a JSON of the kind {"event" : "anotherEvent", "data" : {}} is received
|
||||||
|
socket.on("anotherEvent", (data) => {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// same as calling socket.addEventListener("open") on a regular WebSocket
|
||||||
|
// same behaviour applies to events "close", "error" and "message"
|
||||||
|
socket.on("open", (event) => {
|
||||||
|
console.log(event);
|
||||||
|
});
|
||||||
|
```
|
|
@ -0,0 +1,176 @@
|
||||||
|
class SmartWebSocket{
|
||||||
|
|
||||||
|
socket;
|
||||||
|
url;
|
||||||
|
protocols;
|
||||||
|
debugName;
|
||||||
|
|
||||||
|
autoreconnect;
|
||||||
|
|
||||||
|
#events;
|
||||||
|
#reconnecting;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(url, protocols = [], autoreconnect = true, debugName = null) {
|
||||||
|
this.url = url;
|
||||||
|
this.protocols = protocols;
|
||||||
|
this.autoreconnect = autoreconnect;
|
||||||
|
this.debugName = debugName;
|
||||||
|
|
||||||
|
this.#events = {};
|
||||||
|
this.#reconnecting = false;
|
||||||
|
|
||||||
|
this.#connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
#formatedConsole(method, message, color) {
|
||||||
|
if (color && typeof message == "string") {
|
||||||
|
console[method]("%c%s\t | %c%s", "font-weight: bold; color: cyan;", this.debugName ?? this.url, `color: ${color};`, message);
|
||||||
|
} else {
|
||||||
|
console[method]("%c%s\t | %c%s", "font-weight: bold; color: cyan;", this.debugName ?? this.url, "", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#log(message, color = null) {
|
||||||
|
this.#formatedConsole("log", message, color);
|
||||||
|
}
|
||||||
|
#error(message) {
|
||||||
|
this.#formatedConsole("error", message);
|
||||||
|
}
|
||||||
|
#warn(message) {
|
||||||
|
this.#formatedConsole("warn", message);
|
||||||
|
}
|
||||||
|
#info(message, color = null) {
|
||||||
|
this.#formatedConsole("info", message, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#connect() {
|
||||||
|
this.#info("Connecting socket...", "yellow");
|
||||||
|
this.socket = new WebSocket(this.url, this.protocols);
|
||||||
|
|
||||||
|
this.socket.addEventListener("open", (eventData) => this.#openHandler(eventData));
|
||||||
|
this.socket.addEventListener("close", (eventData) => this.#closeHandler(eventData));
|
||||||
|
this.socket.addEventListener("error", (eventData) => this.#errorHandler(eventData));
|
||||||
|
this.socket.addEventListener("message", (eventData) => this.#messageHandler(eventData));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#eventHandler(event, data = null) {
|
||||||
|
if (!(event in this.#events)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.#events[event].length; i++) {
|
||||||
|
this.#events[event][i](data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#openHandler(eventData) {
|
||||||
|
this.#info("Socket connected.", "lime");
|
||||||
|
this.#reconnecting = false;
|
||||||
|
|
||||||
|
this.#eventHandler("open", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#closeHandler(eventData) {
|
||||||
|
if (eventData.wasClean) {
|
||||||
|
this.#info("Socket disconnected cleanly.");
|
||||||
|
} else {
|
||||||
|
if (!this.#reconnecting) {
|
||||||
|
this.#warn("Socket disconnected apruptly!");
|
||||||
|
if (!this.autoreconnect) {
|
||||||
|
this.#warn("autoreconnect is set to false! Socket will not automatically reconnect in case of an unexpected loss of connection.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.autoreconnect) {
|
||||||
|
if (!this.#reconnecting) {
|
||||||
|
this.#info("Automatically reconnecting.");
|
||||||
|
this.#reconnecting = true;
|
||||||
|
}
|
||||||
|
this.reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#eventHandler("close", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#errorHandler(eventData) {
|
||||||
|
if (!this.#reconnecting) {
|
||||||
|
this.#error(eventData);
|
||||||
|
}
|
||||||
|
this.#eventHandler("error", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#messageHandler(eventData) {
|
||||||
|
let jsonObj = false;
|
||||||
|
try {
|
||||||
|
jsonObj = JSON.parse(eventData.data);
|
||||||
|
} catch (err) {
|
||||||
|
this.#warn("received non-JSON data from WebSocket");
|
||||||
|
jsonObj = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObj && "event" in jsonObj) {
|
||||||
|
if ("data" in jsonObj) {
|
||||||
|
this.#eventHandler(jsonObj.event, jsonObj.data);
|
||||||
|
} else {
|
||||||
|
this.#eventHandler(jdonObj.event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#eventHandler("message", eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnect() {
|
||||||
|
if (this.socket != undefined && this.socket.readyState < 3) {
|
||||||
|
if (!this.autoreconnect) {
|
||||||
|
this.socket.addEventListener("close", () => this.#connect());
|
||||||
|
}
|
||||||
|
this.socket.close();
|
||||||
|
this.#info("Closing socket.", "lime")
|
||||||
|
} else {
|
||||||
|
this.#connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
if (this.socket.readyState == 4) {
|
||||||
|
throw "socket already closed";
|
||||||
|
}
|
||||||
|
this.autoreconnect = false;
|
||||||
|
this.socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
isReady() {
|
||||||
|
return this.socket.readyState == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
on(event, handler) {
|
||||||
|
if (typeof event != "string") {
|
||||||
|
throw "argument event is expected to be of type string";
|
||||||
|
}
|
||||||
|
if (typeof handler != "function") {
|
||||||
|
throw "argument handler is expected to be of type function";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event in this.#events) {
|
||||||
|
this.#events[event].push(handler);
|
||||||
|
} else {
|
||||||
|
this.#events[event] = [handler];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send(event, data = null) {
|
||||||
|
if (typeof event != "string") {
|
||||||
|
throw "argument event is expected to be of type string";
|
||||||
|
}
|
||||||
|
this.socket.send(JSON.stringify({event: event, data: data}));
|
||||||
|
}
|
||||||
|
|
||||||
|
sendRaw(data) {
|
||||||
|
this.socket.send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
get events() {
|
||||||
|
return this.#events;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue