comty.js/src/rtclient.js

132 lines
2.2 KiB
JavaScript

export class RTEngineClient {
constructor(params = {}) {
this.params = params
}
socket = null
stateSubscribers = []
joinedTopics = new Set()
handlers = new Set()
async connect() {
return new Promise((resolve, reject) => {
if (this.socket) {
this.disconnect()
}
let url = `${this.params.url}`
if (this.params.token) {
url += `?token=${this.params.token}`
}
this.socket = new WebSocket(url)
this.socket.onopen = () => {
resolve()
this._emit("connect")
}
this.socket.onclose = () => {
this._emit("disconnect")
}
this.socket.onerror = () => {
reject()
this._emit("error")
}
this.socket.onmessage = (event) => this.handleMessage(event)
})
}
async disconnect() {
if (!this.socket) {
return false
}
for await (const topic of this.joinedTopics) {
this.leaveTopic(topic)
}
this.socket.close()
this.socket = null
}
_emit(event, data) {
for (const handler of this.handlers) {
if (handler.event === event) {
handler.handler(data)
}
}
}
on = (event, handler) => {
this.handlers.add({
event,
handler,
})
}
off = (event, handler) => {
this.handlers.delete({
event,
handler,
})
}
emit = (event, data) => {
if (!this.socket) {
throw new Error("Failed to send, socket not connected")
}
this.socket.send(JSON.stringify({ event, data }))
}
joinTopic = (topic) => {
this.emit("topic:join", topic)
this.joinedTopics.add(topic)
}
leaveTopic = (topic) => {
this.emit("topic:leave", topic)
this.joinedTopics.delete(topic)
}
updateState(state) {
this.stateSubscribers.forEach((callback) => callback(state))
}
//* HANDLERS
handleMessage(event) {
try {
const payload = JSON.parse(event.data)
if (typeof payload.event !== "string") {
return false
}
if (payload.event === "error") {
console.error(payload.data)
return false
}
this._emit(payload.event, payload.data)
} catch (error) {
console.error("Error handling message:", error)
}
}
// UPDATERS
onStateChange(callback) {
this.stateSubscribers.push(callback)
return () => {
this.stateSubscribers = this.stateSubscribers.filter(
(cb) => cb !== callback,
)
}
}
}
export default RTEngineClient