小程序實現心跳機制

export default class websocket {
  constructor({ heartCheck, isReconnection }) {
    // 是否連接
    this._isLogin = false;
    // 當前網絡狀態
    this._netWork = true;
    // 是否人爲退出
    this._isClosed = false;
    // 心跳檢測頻率
    this._timeout = 3000;
    this._timeoutObj = null;
    // 當前重連次數
    this._connectNum = 0;
    // 心跳檢測和斷線重連開關,true爲啓用,false爲關閉
    this._heartCheck = heartCheck;
    this._isReconnection = isReconnection;
    this._onSocketOpened();
  }
  // 心跳重置
  _reset() {
    clearTimeout(this._timeoutObj);
    return this;
  }
  // 心跳開始
  _start() {
    let _this = this;
    this._timeoutObj = setInterval(() => {
      wx.sendSocketMessage({
        // 心跳發送的信息應由前後端商量後決定
        data: JSON.stringify({
          "key": 'value'
        }),
        success(res) {
          console.log(res)
          console.log("發送心跳成功");
        },
        fail(err) {
          console.log(err)
          _this._reset()
        }
      });
    }, this._timeout);
  }
  // 監聽websocket連接關閉
  onSocketClosed(options) {
    wx.onSocketClose(err => {
      console.log('當前websocket連接已關閉,錯誤信息爲:' + JSON.stringify(err));
      // 停止心跳連接
      if (this._heartCheck) {
        this._reset();
      }
      // 關閉已登錄開關
      this._isLogin = false;
      // 檢測是否是用戶自己退出小程序
      if (!this._isClosed) {
        // 進行重連
        if (this._isReconnection) {
          this._reConnect(options)
        }
      }
      
    })
  }
  // 檢測網絡變化
  onNetworkChange(options) {
    wx.onNetworkStatusChange(res => {
      console.log('當前網絡狀態:' + res.isConnected);
      if (!this._netWork) {
        this._isLogin = false;
        // 進行重連
        if (this._isReconnection) {
          this._reConnect(options)
        }
      }
    })
  }
  _onSocketOpened() {
    wx.onSocketOpen(res => {
      console.log('websocket已打開');
      // 打開已登錄開關
      this._isLogin = true;
      // 發送心跳
      if (this._heartCheck) {
        this._reset()._start();
      }
      // 發送登錄信息
      wx.sendSocketMessage({
        // 這裏是第一次建立連接所發送的信息,應由前後端商量後決定
        data: JSON.stringify({
          "key": 'value'
        })
      })
      // 打開網絡開關
      this._netWork = true;
    })
  }
  // 接收服務器返回的消息
  onReceivedMsg(callBack) {
    wx.onSocketMessage(msg => {
      if (typeof callBack == "function") {
        callBack(msg)
      } else {
        console.log('參數的類型必須爲函數')
      }
    })
  }

  // 建立websocket連接
  initWebSocket(options) {
    let _this = this;
    if (this._isLogin) {
      console.log("您已經登錄了");
    } else {
      // 檢查網絡
      wx.getNetworkType({
        success(result) {
          if (result.networkType != 'none') {
            // 開始建立連接
            wx.connectSocket({
              url: options.url,
              success(res) {
                if (typeof options.success == "function") {
                  options.success(res)
                } else {
                  console.log('參數的類型必須爲函數')
                }
              },
              fail(err) {
                if (typeof options.fail == "function") {
                  options.fail(err)
                } else {
                  console.log('參數的類型必須爲函數')
                }
              }
            })
          } else {
            console.log('網絡已斷開');
            _this._netWork = false;
            // 網絡斷開後顯示model
            wx.showModal({
              title: '網絡錯誤',
              content: '請重新打開網絡',
              showCancel: false,
              success: function (res) {
                if (res.confirm) {
                  console.log('用戶點擊確定')
                }
              }
            })
          }
        }
      })
    }
  }
  // 發送websocket消息
  sendWebSocketMsg(options) {
    wx.sendSocketMessage({
      data: options.data,
      success(res) {
        if (typeof options.success == "function") {
          options.success(res)
        } else {
          console.log('參數的類型必須爲函數')
        }
      },
      fail(err) {
        if (typeof options.fail == "function") {
          options.fail(err)
        } else {
          console.log('參數的類型必須爲函數')
        }
      }
    })
  }
  // 重連方法,會根據時間頻率越來越慢
  _reConnect(options) {
    let timer, _this = this;
    if (this._connectNum < 20) {
      timer = setTimeout(() => {
        this.initWebSocket(options)
      }, 3000)
      this._connectNum += 1;
    } else if (this._connectNum < 50) {
      timer = setTimeout(() => {
        this.initWebSocket(options)
      }, 10000)
      this._connectNum += 1;
    } else {
      timer = setTimeout(() => {
        this.initWebSocket(options)
      }, 450000)
      this._connectNum += 1;
    }
  }
  // 關閉websocket連接
  closeWebSocket(){
    wx.closeSocket();
    this._isClosed = true;
  }
}

使用方法
在app.js裏面引入,然後在onLaunch裏面創建
import websocket from './utils/wechat-websocket.js'

//app.js
App({
  onLaunch() {
    let _this = this;
    // 創建websocket對象
    this.websocket = new websocket({
      // true代表啓用心跳檢測和斷線重連
      heartCheck: true,
      isReconnection: true
    });
    // 建立連接
    this.linkWebsocket();
    // 監聽websocket狀態
    this.websocket.onSocketClosed({
      url: this.globalData.websocketUrl,
      success(res) { console.log(res) },
      fail(err) { console.log(err) }
    })
    // 監聽網絡變化
    this.websocket.onNetworkChange({
      url: this.globalData.websocketUrl,
      success(res) { console.log(res) },
      fail(err) { console.log(err) }
    })
    // 監聽服務器返回
    this.websocket.onReceivedMsg(result => {
      console.log('app.js收到服務器內容:' + result.data);
      // 要進行的操作
    })
  },
  onHide(){
    // 程序後臺後的操作--關閉websocket連接
    this.websocket.closeWebSocket();
  },
  onShow(){
    // 程序從後臺到前臺的操作--建立連接
    this.linkWebsocket();
  }.
  linkWebsocket() {
    // 建立連接
    this.websocket.initWebSocket({
      url: this.globalData.websocketUrl,
      success(res) { console.log(res) },
      fail(err) { console.log(err) }
    })
  },
  getWebSocket() {
    // 向其他頁面暴露當前websocket連接
    return this.websocket;
  },
  globalData: {
    websocketUrl: 'wss://xxx.com/websocket'
  }
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章