From 43269c82e692034301d589ffaeb6550eeb78b90e Mon Sep 17 00:00:00 2001 From: Luk Date: Sun, 4 Feb 2024 11:29:25 +0800 Subject: [PATCH] add heartbeating --- unisocket.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/unisocket.js b/unisocket.js index a035c22..30dac32 100644 --- a/unisocket.js +++ b/unisocket.js @@ -1,49 +1,60 @@ const my = { socket: undefined, reconnecting: undefined, + heartbeating: undefined, listeners: {}, } export default { - initSocket (url, reconnect = false) { + initSocket (url, relogin = false) { if (!my.socket || (my.socket.readyState !== my.socket.OPEN && typeof url === 'string')) { - console.log(`WebSocket is connecting to ${url}...`) + console.log(new Date().toJSON(), `WebSocket is connecting to ${url}...`) my.socket = uni.connectSocket({ url: url.replace(/^http/, 'ws'), - complete: () => {}, + complete: () => { }, }) my.socket.onOpen((res) => { - console.log('WebSocket onOpen: ', res) + console.log(new Date().toJSON(), 'WebSocket onOpen: ', res) clearInterval(my.reconnecting) delete my.reconnecting - if (reconnect && uni.getStorageSync('_passtoken')) { - console.log('Reporting owner for reconnecting socket') + // 前端断线重连时,并不会自动提供 _passtoken。在前端的initSocket时,应当把_passtoken送过来,而后台则对_passtoken做验证后再加socketPool。 + if (relogin && uni.getStorageSync('_passtoken')) { + console.log(new Date().toJSON(), 'Reporting owner for reconnecting socket') 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 + } + }, 20000) // 定期发送心跳,避免被关闭 }) my.socket.onClose((res) => { - console.log('Websocket onClose: ', res) + console.log(new Date().toJSON(), 'Websocket onClose: ', res) if (!my.reconnecting) my.reconnecting = setInterval(() => { - console.log(new Date().toJSON(), 'WebSocket reconnecting...') + console.log(new Date().toJSON(), 'Websocket reconnecting...') this.initSocket(url, true) }, 5000) // 每5秒尝试重连 }) my.socket.onError((err) => { - console.log('Websocket onError: ', err) + console.log(new Date().toJSON(), 'Websocket onError: ', err) }) my.socket.onMessage(({ data }) => { // 在这里统一分发消息(用户端通常不需要返回结果给服务器,因此不用 rpc 模式,而用 event 模式。 try { let { skevent, ...apiWhat } = JSON.parse(data) - console.log('WebSocket onMessage for skevent: ', skevent) + console.log(new Date().toJSON(), 'Websocket onMessage for skevent: ', skevent) let listeners = my.listeners[skevent] || [] for (let listener of listeners) { listener(apiWhat) } } catch (exception) { - console.log(new Date().toJSON(), 'unknown message', data, exception) + console.log(new Date().toJSON(), 'Websocket onMessage unknown', data, exception) return } })