function Message(obj, conn) { this.isResponsable = function() { return obj.id >= 0 } this.sendResponse = function(data) { conn.send({ id: obj.id, is_response: true, data: data }) } this.data = function() { return obj.data } return this } /* { connected: function сlosed: function incoming: function } */ function Conn(addr, callback = {}) { self = this let socket = null let connected = false let rStore = {} let idCounter = 0, idMax = Math.pow(2, 62) let mQueue = [] function nextID() { idCounter += 1 if (idCounter == idMax) idCounter = 0 return idCounter } function connect() { socket = new WebSocket("ws://" + addr + "/api") socket.onopen = function(e) { connected = true if (callback.connected != null) callback.connected() //console.log('connected', mQueue) mQueue.forEach(function(obj) { self.sendMessage(obj.obj, obj.rCallback, obj.deadline) }) mQueue = [] } socket.onclose = function(e) { //console.log('close...') connected = false if (callback.closed != null) callback.closed() setTimeout(function() { self.reconnect() }, 3000) } socket.onmessage = function(e) { let mObj = JSON.parse(e.data) //console.log(mObj) if (mObj.is_response) { //console.log('response') let rCall = rStore[mObj.id] //console.log('rc', rCall, rStore) if (rCall) { clearTimeout(rCall.cancel) delete rStore[mObj.id] rCall.callback(mObj.data) //console.log(rStore) } } else { let m = new Message(mObj, self) callback.incoming(m) } } } this.reconnect = function() { //console.log('reconnect', connected) connect() } function send (obj) { if (!connected) { return } socket.send(JSON.stringify(obj)) } this.sendMessage = function(obj, rCallback, deadline = 30000) { if (!connected) { mQueue.push({ obj: obj, rCallback: rCallback, deadline: deadline }) return } if (deadline == 0) { send({ id: id, data: obj, }) } else { let id = nextID() send({ id: id, data: obj, }) let cancel = setTimeout(function() { delete rStore[id] }, deadline) rStore[id] = { cancel: cancel, callback: rCallback, } } } connect() return self }