const my = { socket: undefined, reconnecting: undefined, listeners: {}, } export default { initSocket (url, reconnect = false) { if (!my.socket || (my.socket.readyState !== my.socket.OPEN && typeof url === 'string')) { console.log(`WebSocket is connecting to ${url}...`) my.socket = uni.connectSocket({ url: url.replace(/^http/, 'ws'), complete: () => {}, }) my.socket.onOpen((res) => { console.log('WebSocket onOpen: ', res) clearInterval(my.reconnecting) delete my.reconnecting if (reconnect && uni.getStorageSync('_passtoken')) { console.log('Reporting owner for reconnecting socket') my.socket.send({ data: JSON.stringify({ skevent: 'SOCKET_OWNER', _passtoken: uni.getStorageSync('_passtoken') }) }) } }) my.socket.onClose((res) => { console.log('Websocket onClose: ', res) if (!my.reconnecting) my.reconnecting = setInterval(() => { console.log(new Date().toJSON(), 'WebSocket reconnecting...') this.initSocket(url, true) }, 5000) // 每5秒尝试重连 }) my.socket.onError((err) => { console.log('Websocket onError: ', err) }) my.socket.onMessage(({ data }) => { // 在这里统一分发消息(用户端通常不需要返回结果给服务器,因此不用 rpc 模式,而用 event 模式。 try { let dataObj = JSON.parse(data) console.log('WebSocket onMessage for skevent: ', dataObj.skevent) let listeners = my.listeners[dataObj.skevent] || [] for (let listener of listeners) { listener(dataObj) } } catch (exception) { console.log(new Date().toJSON(), 'unknown message', data) return } }) } return this }, closeSocket () { if (my.socket) my.socket.close() setTimeout(() => { clearInterval(my.reconnecting) delete my.reconnecting }, 2000) }, addListener (skevent, listener) { if (Array.isArray(my.listeners[skevent]) && typeof listener === 'function') { my.listeners[skevent].push(listener) } else { my.listeners[skevent] = [listener] } return this }, countListener (skevent) { if (Array.isArray(my.listeners[skevent])) { return my.listeners[skevent].length } return 0 }, sendObject (dataObj) { if (my.socket && my.socket.readyState === my.socket.OPEN) { my.socket.send({ data: typeof dataObj !== 'string' ? JSON.stringify(dataObj) : dataObj, }) } }, }