vue3中实现websocket

方式1 websocket 在vuex中实现
import { createStore } from 'vuex'
import { socket } from '@/types/vuex'
import storage from 'store'

const state: socket = {
  //推送消息
  data: {},
  webSocket: null,
  timer: null,
  hearbeat_interval: 1000 * 2
}

const store = createStore({
  state,
  getters: {

    getData: state => state.data
  },
  mutations: {

    initWebsocket(state) {
      state.webSocket = new WebSocket(
        'ws://localhost:8000'
      )
      state.webSocket.onopen = function () {
        console.log('通讯开始')

        state.timer && clearInterval(state.timer)
        state.timer = setInterval(() => {
          state.webSocket.send(JSON.stringify({
            // token: storage.get('token')
            token: Math.random()
          }))
        }, state.hearbeat_interval)

      }
      state.webSocket.onmessage = function (e: { data: string | Object }) {
        console.log('收到的数据:', e.data)
        let data = JSON.parse(e.data as string)
        state.data = e.data
        // console.log(data)
      }
      state.webSocket.onerror = function () {
        console.log('通讯异常')
      }
      state.webSocket.onclose = function () {
        console.log('连接已断开')
        state.timer && clearInterval(state.timer)
      }
    },
  },
  actions: {
  },
  modules: {
  }
})
export default store;

// 在组件中使用
import {
  ref,
  defineComponent,
  watch,
} from 'vue'

import { useStore } from 'vuex'
export default defineComponent({
setup(){
const store = useStore()
    const initSocket = () => {
      store.commit('initWebsocket')
    }
    onBeforeMount(() => {
      initSocket()
      console.log('store', store)
    })

    onUnmounted(() => {
      // ws.close()
      store.state.webSocket.close()
    })

    const data = ref('')
    watch(
      () => store.getters.getData,
      (newValue, oldValue) => {
        data.value = newValue
        console.log('watch 已触发', newValue)
      }
    )

return { data }
}
})
 
@/types/vuex/index.ts中定义一个接口
export interface socket {
  webSocket: any
  data: Object
  [propName: string]: any
}
 
方式2 websocket 在utils中单独封装
 
import { ElMessage as message } from 'element-plus'
import storage from 'store'
import socket from '@/types/api/socket'
const socket: socket = {
  websocket: null,
  connectURL: 'ws://localhost:8000',
  // 开启标识
  socket_open: false,
  // 心跳timer
  hearbeat_timer: null,
  // 心跳发送频率
  hearbeat_interval: 2 * 1000,
  // 是否自动重连
  is_reonnect: true,
  // 重连次数
  reconnect_count: 3,
  // 已发起重连次数
  reconnect_current: 1,
  // 重连timer
  reconnect_timer: null,
  // 重连频率
  reconnect_interval: 5 * 1000,
  init: (receiveMessage: Function | null) => {
    if (!('WebSocket' in window)) {
      message.warning('浏览器不支持WebSocket')
      return null
    }
    socket.websocket = new WebSocket(socket.connectURL)
    socket.websocket.onmessage = (e: any) => {
      if (receiveMessage) {
        receiveMessage(e)
      }
    }
    socket.websocket.onclose = (e: any) => {
      socket.socket_open = false
      // 需要重新连接
      if (socket.is_reonnect) {
        socket.reconnect_timer = setTimeout(() => {
          // 超过重连次数
          if (socket.reconnect_current > socket.reconnect_count) {
            clearTimeout(socket.reconnect_timer)
            socket.is_reonnect = false
            return
          }
          // 记录重连次数
          socket.reconnect_current++
          socket.reconnect()
        }, socket.reconnect_interval)
      }
    }
    // 连接成功
    socket.websocket.onopen = function () {
      socket.socket_open = true
      socket.is_reonnect = true
      // 开启心跳
      socket.heartbeat()
    }
    // 连接发生错误
    socket.websocket.onerror = function () { }
  },
  heartbeat: () => {
    socket.hearbeat_timer && clearInterval(socket.hearbeat_timer)

    socket.hearbeat_timer = setInterval(() => {
      let data = {
        token: storage.get('token')
      }
      socket.send(data)
    }, socket.hearbeat_interval)
  },
  send: (data, callback = null) => {
    // 开启状态直接发送
    if (socket.websocket.readyState === socket.websocket.OPEN) {
      socket.websocket.send(JSON.stringify(data))
      callback && callback()
    } else {
      clearInterval(socket.hearbeat_timer)
      message({
        type: 'warning',
        message: 'socket链接已断开',
        duration: 1000,
      })
    }
  },
  close: () => {
    socket.is_reonnect = false
    socket.websocket.close()
  },
  /**
   * 重新连接
   */
  reconnect: () => {
    if (socket.websocket && !socket.is_reonnect) {
      socket.close()
    }
    socket.init(null)
  },
}
export default socket;

// 在组件中使用

import {
  ref,
  defineComponent,
  onBeforeMount,
  onUnmounted,
} from 'vue'
import socket from '@/utils/socket'

export default defineComponent({
setup(){
 const data = ref('')
    const receive = (message: any) => {
      console.log('message', message.data)
      data.value = message.data
    }

    onBeforeMount(() => {
      socket.init(receive)
    })
    onUnmounted(() => {
      socket.close()
    })
return { data }
}
})

 

posted @ 2022-11-25 16:38  web_cnblogs  阅读(4172)  评论(0)    收藏  举报