小程序websocket(心跳連接)


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();
  },

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM