vue3项目使用webSocket(下载即用) 最佳webSocket封装:支持断线重连、心跳

709 阅读2分钟

新建webSocket.js文件

let ws = null // webSocket实例
const webSocketState = ref(false) //// webSocket的连接状态
const heartBeat = ref({
  // // 心跳连接的时间设置
  time: 5 * 1000, // 心跳时间间隔
  timeout: 3 * 1000, // timeout:心跳超时间隔(!要少于心跳间隔)
  reconnect: 10 * 1000 // 断线重连时间
})
let reconnectTimer = null // 断线重连定时器
const useWebSocket = () => {
  // 关闭连接
  const OnClose = () => {
    ws.close() // 关闭webSocket
    webSocketState.value = false // 设置webSocket状态为关闭
    heartBeat.value.time = null // 清空心跳时间 停止心跳
    if (reconnectTimer) {
      //关闭重连定时器
      clearTimeout(reconnectTimer)
    }
  }

  //   开启连接
  const OnLocation = () => {
    heartBeat.value.time = 5 * 1000 //因为关闭时会置空,所以在这重新初始化一下
    connectWebSocket() //建立连接
  }

  //   建立连接
  const connectWebSocket = () => {
    let url = `http://semiauto.aarobot.com/v1.0/message`
    //这里连接地址根据自己的业务设置,注意:如果连接本地进行调试的时候,要用'ws',如:“ws://192.168.2.15:8080/msg”
    ws = new WebSocket(url)
    init() //初始化
  }

  //   初始化
  const init = () => {
    ws.addEventListener('open', () => {
      webSocketState.value = true //socket状态设置为连接,做为后面的断线重连的拦截器
      console.log('开启')
      heartBeat.value && heartBeat.value.time ? startHeartBeat(heartBeat.value.time) : '' // 是否启动心跳机制
    })
    ws.addEventListener('message', (e) => {
      webSocketState.value = true
      console.log(JSON.parse(e.data), '信息')
    })
    ws.addEventListener('close', (e) => {
      webSocketState.value = false // socket状态设置为断线
      console.log('断开了连接', e)
    })
    ws.addEventListener('error', (e) => {
      webSocketState.value = false // socket状态设置为断线
      reconnectWebSocket() // 重连
      console.log('连接发生了错误', e)
    })
  }
  // 心跳  time:心跳时间间隔
  const startHeartBeat = (time) => {
    setTimeout(() => {
      //这里设置这是你要发送的内容 如果后端没有设置心跳,则不需要发送
      //   let data = {} //data 发送给服务端的数据
      //   ws.send(JSON.stringify(data)) //发送数据
      waitingServer()
    }, time)
  }

  // 延时等待服务端响应,通过webSocketState判断是否连线成功
  const waitingServer = () => {
    webSocketState.value = false
    setTimeout(() => {
      if (webSocketState.value) {
        startHeartBeat(heartBeat.value.time)
        return
      }
      console.log('心跳无响应,已断线')
      try {
        ws.close()
      } catch (e) {
        console.log('连接已关闭,无需关闭')
      }
      reconnectWebSocket() //非主动关闭导致,触发重连
    }, heartBeat.value.timeout)
  }

  // 重连操作
  const reconnectWebSocket = () => {
    reconnectTimer = setTimeout(() => {
      console.log('重连中...')
      reconnectWs()
    }, heartBeat.value.reconnect)
  }

  const reconnectWs = () => {
    if (!heartBeat.value.time) return //如果主动关闭,则防止重连
    if (!ws) {
      // 第一次执行,初始化
      connectWebSocket()
    }
    if (ws && reconnectTimer) {
      // 防止多个websocket同时执行
      clearTimeout(reconnectTimer)
      ws.reconnectTimer = null
      connectWebSocket()
    }
  }
  return {
    OnLocation,
    OnClose
  }
}

export default useWebSocket

由于个人项目是全局所以将放到app.vue里

import useWebSocket from '@/utils/webSocket'
const { OnLocation, OnClose } = useWebSocket()
//连接
OnLocation()
//关闭连接
OnClose()

原文链接