uniapp小程序webSocket封裝、斷線重連、心跳檢測

1,前言

最近在做IOT的項(xiàng)目,里面有個(gè)小程序要用到webSocket,借這個(gè)機(jī)會(huì),封裝了一個(gè)uniapp小程序適用的Socket類,包括斷線重連,心跳檢測等等,具體實(shí)現(xiàn)如下。

2,代碼實(shí)現(xiàn)

class webSocketClass {
  constructor(url, time) {
    this.url = url
    this.data = null
    this.isCreate = false // WebSocket 是否創(chuàng)建成功
    this.isConnect = false // 是否已經(jīng)連接
    this.isInitiative = false // 是否主動(dòng)斷開
    this.timeoutNumber = time // 心跳檢測間隔
    this.heartbeatTimer = null // 心跳檢測定時(shí)器
    this.reconnectTimer = null // 斷線重連定時(shí)器
    this.socketExamples = null // websocket實(shí)例
    this.againTime = 3 // 重連等待時(shí)間(單位秒)
  }

  // 初始化websocket連接
  initSocket() {
    const _this = this
    this.socketExamples = uni.connectSocket({
      url: _this.url,
      header: {
        'content-type': 'application/json'
      },
      success: (res) => {
        _this.isCreate = true
        console.log(res)
      },
      fail: (rej) => {
        console.error(rej)
        _this.isCreate = false
      }
    })
    this.createSocket()
  }

  // 創(chuàng)建websocket連接
  createSocket() {
    if (this.isCreate) {
      console.log('WebSocket 開始初始化')
      // 監(jiān)聽 WebSocket 連接打開事件
      try {
        this.socketExamples.onOpen(() => {
          console.log('WebSocket 連接成功')
          this.isConnect = true
          clearInterval(this.heartbeatTimer)
          clearTimeout(this.reconnectTimer)
          // 打開心跳檢測
          this.heartbeatCheck()
        })
        // 監(jiān)聽 WebSocket 接受到服務(wù)器的消息事件
        this.socketExamples.onMessage((res) => {
          console.log('收到消息')
          uni.$emit('message', res)
        })
        // 監(jiān)聽 WebSocket 連接關(guān)閉事件
        this.socketExamples.onClose(() => {
          console.log('WebSocket 關(guān)閉了')
          this.isConnect = false
          this.reconnect()
        })
        // 監(jiān)聽 WebSocket 錯(cuò)誤事件
        this.socketExamples.onError((res) => {
          console.log('WebSocket 出錯(cuò)了')
          console.log(res)
          this.isInitiative = false
        })
      } catch (error) {
        console.warn(error)
      }
    } else {
      console.warn('WebSocket 初始化失敗!')
    }
  }

  // 發(fā)送消息
  sendMsg(value) {
    const param = JSON.stringify(value)
    return new Promise((resolve, reject) => {
      this.socketExamples.send({
        data: param,
        success() {
          console.log('消息發(fā)送成功')
          resolve(true)
        },
        fail(error) {
          console.log('消息發(fā)送失敗')
          reject(error)
        }
      })
    })
  }

  // 開啟心跳檢測
  heartbeatCheck() {
    console.log('開啟心跳')
    this.data = { state: 1, method: 'heartbeat' }
    this.heartbeatTimer = setInterval(() => {
      this.sendMsg(this.data)
    }, this.timeoutNumber * 1000)
  }

  // 重新連接
  reconnect() {
    // 停止發(fā)送心跳
    clearTimeout(this.reconnectTimer)
    clearInterval(this.heartbeatTimer)
    // 如果不是人為關(guān)閉的話,進(jìn)行重連
    if (!this.isInitiative) {
      this.reconnectTimer = setTimeout(() => {
        this.initSocket()
      }, this.againTime * 1000)
    }
  }

  // 關(guān)閉 WebSocket 連接
  closeSocket(reason = '關(guān)閉') {
    const _this = this
    this.socketExamples.close({
      reason,
      success() {
        _this.data = null
        _this.isCreate = false
        _this.isConnect = false
        _this.isInitiative = true
        _this.socketExamples = null
        clearInterval(_this.heartbeatTimer)
        clearTimeout(_this.reconnectTimer)
        console.log('關(guān)閉 WebSocket 成功')
      },
      fail() {
        console.log('關(guān)閉 WebSocket 失敗')
      }
    })
  }
}

export default webSocketClass

3,使用

直接實(shí)例化封裝的socket類,調(diào)用initSocket初始化就行了,當(dāng)收到消息的時(shí)候,會(huì)觸發(fā)全局$emit事件,只需要使用$on監(jiān)聽message事件就行。

3.1,初始化

我這邊在globalData里面定義了socketObj全局變量,在首頁onShow生命周期里面判斷當(dāng)前是否已經(jīng)初始化了socket實(shí)例,再進(jìn)行操作。

home.vue

import WebSocketClass from '../../utils/webSocket'
const app = getApp()

onShow() {
  // 如果已登陸,則啟用WebSocket
    if (app.globalData.user && app.globalData.user.sToken) {
      // 如果已經(jīng)有sockt實(shí)例
      if (app.globalData.socketObj) {
        // 如果sockt實(shí)例未連接
        if (!app.globalData.socketObj.isConnect) {
          app.globalData.socketObj.initSocket()
        }
      } else {
        // 如果沒有sockt實(shí)例,則創(chuàng)建
        const data = app.globalData.user
        const path = `/websocket/notify/${data.userId}`
        app.globalData.socketObj = new WebSocketClass(
          `${app.globalData.socketUrl}${path}?token=${data.userToken}&refreshToken=${data.sToken}`,
          60
        )
        app.globalData.socketObj.initSocket()
      }
    }
}

3.2,發(fā)送消息

methods: {
  sendMessage() {
    const param = { value: '我是一個(gè)消息' }
    app.globalData.socketObj.sendMsg(param)
  }
}

3.3,接收消息

// 開啟監(jiān)聽
onLoad() {
  uni.$on('message', this.getMessage)
},
// 頁面卸載時(shí)取消監(jiān)聽
onUnload() {
  uni.$off('message', this.getMessage)
},
methods: {
  // 接收到消息的回調(diào)
  getMessage(msg) {
    console.log(msg)
  }
}

3.4,斷線重連

斷線會(huì)自動(dòng)重連。

斷線重連

如果看了覺得有幫助的,我是@鵬多多11997110103,歡迎 點(diǎn)贊 關(guān)注 評(píng)論;
END

PS:在本頁按F12,在console中輸入document.querySelectorAll('._2VdqdF')[0].click(),有驚喜哦

往期文章

個(gè)人主頁

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容