From 61e441b59608f879de582c7c48f3a664d4fe151b Mon Sep 17 00:00:00 2001 From: Luk Date: Wed, 18 Sep 2024 10:23:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=83=E8=BE=9B=E4=B8=87=E8=8B=A6=E4=B8=80?= =?UTF-8?q?=E6=95=B4=E5=A4=A9=E5=A4=9A=E5=8F=91=E7=8E=B0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E9=9A=90=E8=94=BDbug:=20uni.connectSocket=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=90=8E=EF=BC=8Csocket=20=E5=BE=88=E5=8F=AF=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E6=9C=AA=20open=EF=BC=8C=E5=AF=BC=E8=87=B4=E8=BF=99=E6=9C=9F?= =?UTF-8?q?=E9=97=B4=E7=9A=84=20sendObject({skevent:'SOCKET=5FOWNER'})=20?= =?UTF-8?q?=E4=BC=9A=E9=9D=99=E6=82=84=E6=82=84=E5=A4=B1=E8=B4=A5=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=90=8E=E5=8F=B0=E7=9A=84=20socket.skid/usi?= =?UTF-8?q?d=20=E5=B9=B6=E6=9C=AA=E8=A2=AB=E6=AD=A3=E7=A1=AE=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E3=80=82=E9=80=9A=E8=BF=87=E8=AE=BE=E7=BD=AE=20messag?= =?UTF-8?q?eQueue=20=E6=9D=A5=E8=A7=A3=E5=86=B3=E4=BA=86=E8=BF=99=E4=B8=AA?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unisocket.js | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) 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) } }, }