websocket連接之后,如果隔一段時間不聊天,運營商會認為你空占網絡資源,強行關閉你的websocket連接,
如果想要一直保持連接,就需要監聽websocket關閉事件,等關閉時重新連接從而讓websocket一直保持連接.
這個過程稱為心跳
1、必須要有心跳,如果沒有會自動斷開連接。
2‘、斷開后必須取消setTimeout,不然會繼續執行一次。
3、發送消息只有在onSocketOpen后才會發送,所以添加一個消息數組,等連接成功后再發送。
4、如果在還沒連接成功時退出連接,會導致無法關閉,所以添加了socketClose來關閉socket
// socket已經連接成功 var socketOpen = false // socket已經調用關閉function var socketClose = false // socket發送的消息隊列 var socketMsgQueue = [] // 判斷心跳變量 var heart = '' // 心跳失敗次數 var heartBeatFailCount = 0 // 終止心跳 var heartBeatTimeOut = null; // 終止重新連接 var connectSocketTimeOut = null; var webSocket = { /** * 創建一個 WebSocket 連接 * @param {options} * url String 是 開發者服務器接口地址,必須是 wss 協議,且域名必須是后台配置的合法域名 * header Object 否 HTTP Header , header 中不能設置 Referer * method String 否 默認是GET,有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT * protocols StringArray 否 子協議數組 1.4.0 * success Function 否 接口調用成功的回調函數 * fail Function 否 接口調用失敗的回調函數 * complete Function 否 接口調用結束的回調函數(調用成功、失敗都會執行) */ connectSocket: function(options) { wx.showLoading({ title: '', mask: true, }) socketOpen = false socketClose = false socketMsgQueue = [] wx.connectSocket({ url: '開發者服務器接口地', success: function(res) { if (options) { // 成功回調 options.success && options.success(res); } }, fail: function(res) { if (options) { // 失敗回調 options.fail && options.fail(res); } } }) }, /** * 通過 WebSocket 連接發送數據 * @param {options} * data String / ArrayBuffer 是 需要發送的內容 * success Function 否 接口調用成功的回調函數 * fail Function 否 接口調用失敗的回調函數 * complete Function 否 接口調用結束的回調函數(調用成功、失敗都會執行) */ sendSocketMessage: function(options) { if (socketOpen) { wx.sendSocketMessage({ data: options.msg, success: function(res) { if (options) { options.success && options.success(res); } }, fail: function(res) { if (options) { options.fail && options.fail(res); } } }) } else { socketMsgQueue.push(options.msg) } }, /** * 關閉 WebSocket 連接。 * @param {options} * code Number 否 一個數字值表示關閉連接的狀態號,表示連接被關閉的原因。如果這個參數沒有被指定,默認的取值是1000 (表示正常連接關閉) * reason String 否 一個可讀的字符串,表示連接被關閉的原因。這個字符串必須是不長於123字節的UTF-8 文本(不是字符) * fail Function 否 接口調用失敗的回調函數 * complete Function 否 接口調用結束的回調函數(調用成功、失敗都會執行) */ closeSocket: function(options) { if (connectSocketTimeOut) { clearTimeout(connectSocketTimeOut); connectSocketTimeOut = null; } socketClose = true; var self = this; self.stopHeartBeat(); wx.closeSocket({ success: function(res) { console.log('WebSocket 已關閉!'); if (options) { options.success && options.success(res); } }, fail: function(res) { if (options) { options.fail && options.fail(res); } } }) }, // 收到消息回調 onSocketMessageCallback: function(msg) { }, // 開始心跳 startHeartBeat: function() { console.log('socket開始心跳') var self = this; heart = 'heart'; self.heartBeat(); }, // 結束心跳 stopHeartBeat: function() { console.log('socket結束心跳') var self = this; heart = ''; if (heartBeatTimeOut) { clearTimeout(heartBeatTimeOut); heartBeatTimeOut = null; } if (connectSocketTimeOut) { clearTimeout(connectSocketTimeOut); connectSocketTimeOut = null; } }, // 心跳 heartBeat: function() { var self = this; if (!heart) { return; } self.sendSocketMessage({ msg: JSON.stringify({ 'msg_type': 'heart' }), success: function(res) { console.log('socket心跳成功'); if (heart) { heartBeatTimeOut = setTimeout(() => { self.heartBeat(); }, 7000); } }, fail: function(res) { console.log('socket心跳失敗'); if (heartBeatFailCount > 2) { // 重連 self.connectSocket(); } if (heart) { heartBeatTimeOut = setTimeout(() => { self.heartBeat(); }, 7000); } heartBeatFailCount++; }, }); } } // 監聽WebSocket連接打開事件。callback 回調函數 wx.onSocketOpen(function(res) { console.log('WebSocket連接已打開!') wx.hideLoading(); // 如果已經調用過關閉function if (socketClose) { webSocket.closeSocket(); } else { socketOpen = true for (var i = 0; i < socketMsgQueue.length; i++) { webSocket.sendSocketMessage(socketMsgQueue[i]) } socketMsgQueue = [] webSocket.startHeartBeat(); } }) // 監聽WebSocket錯誤。 wx.onSocketError(function(res) { console.log('WebSocket連接打開失敗,請檢查!', res) }) // 監聽WebSocket接受到服務器的消息事件。 wx.onSocketMessage(function(res) { console.log('收到服務器內容:' + res.data) webSocket.onSocketMessageCallback(res.data) }) // 監聽WebSocket關閉。 wx.onSocketClose(function(res) { console.log('WebSocket 已關閉!') if (!socketClose) { clearTimeout(connectSocketTimeOut) connectSocketTimeOut = setTimeout(() => { webSocket.connectSocket(); }, 3000); } }) module.exports = webSocket;
下面是使用方法
// socket連接
const webSocket = require('../../utils/webSocket.js');
onLoad: function(options) {
// 創建連接
webSocket.connectSocket();
// 設置接收消息回調
webSocket.onSocketMessageCallback = this.onSocketMessageCallback;
},
// socket收到的信息回調
onSocketMessageCallback: function(msg) {
console.log('收到消息回調', msg)
},
onUnload: function(options) {
// 頁面銷毀時關閉連接
webSocket.closeSocket();
},