diff --git a/unisocket.js b/unisocket.js index 30e986b..b075a5e 100644 --- a/unisocket.js +++ b/unisocket.js @@ -5,25 +5,35 @@ const my = { listeners: {}, heartbeatInterval: 20000, reconnectInterval: 5000, + messageQueue: [] } +// uni.onSocket* 和 sendSocketMessage/closeSocket 方法,是全局唯一的 api,不需要保存 socket 对象。 +// SocketTask 的 on* 和 send/close 方法,是针对具体 socket 的,适用于多个连接(但不一定支持)或者需要对唯一连接做更精细控制。 + export default { isAlive () { return my.socket && my.socket.readyState === my.socket.OPEN }, - - initSocket ({ url, relogin = false, stateManager = {} } = {}) { + initSocket ({ url, relogin = false, stateManager = {}, heartbeat = false, heartbeatInterval, reconnectInterval } = {}) { if (!my.socket || (my.socket.readyState !== my.socket.OPEN && typeof url === 'string')) { console.log({ _at: new Date().toJSON(), about: `WebSocket is connecting to ${url}...` }) - my.socket = uni.connectSocket({ url: url.replace(/^http/, 'ws'), complete: () => {}, }) - my.socket.onOpen((res) => { console.log({ _at: new Date().toJSON(), about: 'WebSocket onOpen: ', res }) stateManager.socketAlive = true + + if (my.messageQueue.length) { + console.log('WebSocket_onOpen: sending messageQueue') + my.messageQueue.forEach(dataObj => { + this.sendObject(dataObj) + }) + my.messageQueue = [] + } + clearInterval(my.reconnecting) delete my.reconnecting @@ -33,16 +43,17 @@ export default { my.socket.send({ data: JSON.stringify({ skevent: 'SOCKET_OWNER_RECONNECT', _passtoken: uni.getStorageSync('_passtoken') }) }) } - my.heartbeating = setInterval(() => { - if (my.socket && my.socket.readyState === my.socket.OPEN) { - my.socket.send({ data: JSON.stringify({ skevent: 'PING' }) }) - } else { - clearInterval(my.heartbeating) - delete my.heartbeating - } - }, my.heartbeatInterval) // 定期发送心跳,避免被关闭 + if (heartbeat) { + my.heartbeating = setInterval(() => { + if (my.socket && my.socket.readyState === my.socket.OPEN) { + my.socket.send({ data: JSON.stringify({ skevent: 'PING' }) }) + } else { + clearInterval(my.heartbeating) + delete my.heartbeating + } + }, heartbeatInterval || my.heartbeatInterval) // 定期发送心跳,避免被关闭 + } }) - my.socket.onClose((res) => { console.log({ _at: new Date().toJSON(), about: 'Websocket onClose: ', res }) stateManager.socketAlive = false @@ -50,14 +61,12 @@ export default { my.reconnecting = setInterval(() => { console.log({ _at: new Date().toJSON(), about: 'Websocket reconnecting...' }) this.initSocket({ url, relogin: true, stateManager }) - }, my.reconnectInterval) // 定时尝试重连 + }, reconnectInterval || my.reconnectInterval) // 定时尝试重连 }) - my.socket.onError((err) => { console.log({ _at: new Date().toJSON(), about: 'Websocket onError: ', err }) stateManager.socketAlive = false }) - my.socket.onMessage(({ data }) => { // 在这里统一分发消息(用户端通常不需要返回结果给服务器,因此不用 rpc 模式,而用 event 模式。 try { @@ -75,7 +84,6 @@ export default { } return this }, - closeSocket () { if (my.socket) my.socket.close() setTimeout(() => { @@ -83,13 +91,11 @@ export default { delete my.reconnecting }, 2000) }, - initListener (skevent, listener) { // 当该 skevent 尚不具有任何 listener 时,添加本 listener my.listeners[skevent]?.length > 0 || this.addListener(skevent, listener) return this }, - addListener (skevent, listener) { if (Array.isArray(my.listeners[skevent]) && typeof listener === 'function') { my.listeners[skevent].push(listener) @@ -98,19 +104,20 @@ export default { } return this }, - countListener (skevent) { if (Array.isArray(my.listeners[skevent])) { return my.listeners[skevent].length } return 0 }, - sendObject (dataObj) { + console.log('sendObject! socket.readyState =', my.socket.readyState) if (my.socket && my.socket.readyState === my.socket.OPEN) { my.socket.send({ data: typeof dataObj !== 'string' ? JSON.stringify(dataObj) : dataObj, }) + } else { + my.messageQueue.push(dataObj) } }, }