uniapp即时聊天 websocket封装(建立连接、断线重连、心跳机制、主动关闭)

lxf2023-11-23 11:20:01
  1. 使用 SocketTask 的方式去管理 webSocket 链接,每一条链路的生命周期都更加可控
  2. 可实现主动建立连接、心跳防断线机制、断线主动重连、提供主动断开的方法
uniapp即时聊天 websocket封装(建立连接、断线重连、心跳机制、主动关闭)

一、如何使用 (uniapp Vue3)

<template>
  // ...
</template>

<script setup>
  import WS from './websocket'
  import { onLoad, onUnload } from '@dcloudio/uni-app'
  
  // 进入聊天页面初始化
  let ws = null
  onLoad((options) => {
    ws = new WS({
      // 连接websocket所需参数
      data: { userId: options.userId },
      // 首次连接成功之后,断线重新连接后也会触发(防止断线期间对方发送消息未接收到)
      onConnected: () => {
        // toDo
        // 一般用于请求历史消息列表 getHistoryList()
      },
      // 监听接收到服务器消息
      onMessage: (data) => {
        // toDo
        // 一般用于将最新的一条消息展示在页面上
      }
    })
  })
  
  // 发送消息
  function sendMsg() {
    uni.request({
      url: '后端url',
      data: {...},
      success: () => {
        // 发送成功后,上方onMessage会接收到最新消息
      }
    })
  }
  
  // 页面销毁,断开websocket
  onUnload(() => {
    // 主动关闭websocket
    ws.close()
  })
</script>

二、websocket类代码

// 心跳间隔、重连websocket间隔,5秒
const interval = 5000
// 重连最大次数
const maxReconnectMaxTime = 5

export default class WS {
  constructor(options) {
    // 配置
    this.options = options
    // WS实例
    this.socketTask = null

    // 正常关闭
    this.normalCloseFlag = false
    // 重新连接次数
    this.reconnectTime = 1
    // 重新连接Timer
    this.reconnectTimer = null
    // 心跳Timer
    this.heartTimer = null

    // 发起连接
    this.initWS()

    // 关闭WS
    this.close = () => {
      // 正常关闭状态
      this.normalCloseFlag = true
      // 关闭websocket
      this.socketTask.close()
      // 关闭心跳定时器
      clearInterval(this.heartTimer)
      // 关闭重连定时器
      clearTimeout(this.reconnectTimer)
    }
  }

  initWS() {
    // this.options.data 连接websocket所需参数
    const url = 'wss://后端url' + this.options.data.userId
    this.socketTask = uni.connectSocket({ url, success() {} })
    // 监听WS
    this.watchWS()
  }

  watchWS() {
    // 监听 WebSocket 连接打开事件
    this.socketTask.onOpen(() => {
      console('websocket连接成功!')
      // 连接成功
      this.options.onConnected()
      // 重置连接次数
      this.reconnectTime = 1
      // 发送心跳
      this.onHeartBeat()
      // 监听消息
      this.onMessage()
      // 关闭Toast
      uni.hideLoading()
    })

    // 监听websocket 错误
    this.socketTask.onError(() => {
      // 关闭并重连
      this.socketTask.close()
    })

    // 监听 WebSocket 连接关闭事件
    this.socketTask.onClose((res) => {
      // 连接错误,发起重连接
      if (!this.normalCloseFlag) {
        this.onDisconnected(res)
      }
    })
  }

  // 监听消息
  onMessage() {
    // 监听websocket 收到消息
    this.socketTask.onMessage((res) => {
      //收到消息
      if (res.data) {
        this.options.onMessage(JSON.parse(res.data))
      } else {
        console('未监听到消息:原因:', JSON.stringify(res))
      }
    })
  }

  // 断开连接
  onDisconnected(res) {
    console('websocket断开连接,原因:', JSON.stringify(res))
    // 关闭心跳
    clearInterval(this.heartTimer)
    // 全局Toast提示,防止用户继续发送
    uni.showLoading({ title: '消息收取中…' })
    // 尝试重新连接
    this.onReconnect()
  }

  // 断线重连
  onReconnect() {
    clearTimeout(this.reconnectTimer)
    if (this.reconnectTime < maxReconnectMaxTime) {
      this.reconnectTimer = setTimeout(() => {
        console.log(`第【${this.reconnectTime}】次重新连接中……`)
        this.initWS()
        this.reconnectTime++
      }, interval)
    } else {
      uni.showModal({
        title: '温馨提示',
        content: '服务器开小差啦~请返回聊天列表重试',
        showCancel: false,
        confirmText: '我知道了',
        success: () => {
          uni.navigateBack()
        }
      })
    }
  }

  /** @心跳 **/
  onHeartBeat() {
    this.heartTimer = setInterval(() => {
      this.socketTask.send({
        data: `heart:${this.options.data.userId}`,
        success() {
          console.log('心跳发送成功!')
        }
      })
    }, interval)
  }
}
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!