webSocket的使用

本文将一个webSocket封装成hooks的形式,便于使用。
主要思路:
1、根据一个ws/wss地址,创建并初始化一个socket;
2、通过心跳参数heartParam存在与否,判断是否需要对当前socket进行心跳检测;
3、监听异常,socket挂掉后重新创建socket,重复过程1;
4、返回webSocket对象ws和message接收的消息wsData。

/**
 * @name useWebSocket
 * @export
 * @param {url} -(必需)ws/wss地址
 * @param {info} -(不必需)socket运行过程中的一些参数,进房参数joinParams,心跳参数heartParams
 * @returns
 * {ws} -socket对象
 * {wsData} -接收的socket消息
 */
import { useEffect, useState, useRef } from 'react'
let lockReconnect = false // 避免重复连接
const heartCheckSecond = 30 * 1000 // 心跳检测间隔时长

function useWebSocket(url, info) {
  const [wsData, setWsData] = useState({}) // 接收的消息
  const wsRef = useRef(null)
  const { joinParams, heartParams } = info??{}

  useEffect(() => {
    if (!url) return
    createWebSocket()
  }, [url])

  const createWebSocket = () => { // 创建socket连接
    wsRef.current = new WebSocket(url)
    initWebSocket()
  }

  const reconnect = () => { // 创建连接,lockReconnect使当前项目只会存在一个socket
    if (lockReconnect) return
    lockReconnect = true

    setTimeout(function () { // 没连接上会一直重连,设置延迟避免请求过多
      createWebSocket()
      lockReconnect = false
    }, 2000)
  }

  const initWebSocket = () => { // 初始化socket
    wsRef.current.onclose = function (evt) { // 关闭
      console.log('断开连接code:' + evt.code)
      reconnect()
    }

    wsRef.current.onerror = function (evt) { // 连接错误
      console.log('连接失败code:' + evt.code)
      reconnect()
    }

    wsRef.current.onopen = function () {
      var dt = new Date()
      var str = dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate() + ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds()
      console.log('连接成功:' + str)
      wsRef.current.send(joinParams) // 发起c.jr进房操作
      heartParams && heartCheck.reset().start()
    }

    wsRef.current.onmessage = function (evt) {
      var data = JSON.parse(evt.data) // 接收消息string=>json
      setWsData(data)
      heartParams && heartCheck.reset().start()
    }
  }

  let heartCheck = { // 心跳检测
    timeout: heartCheckSecond,
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function() {
      clearTimeout(this.timeoutObj)
      clearTimeout(this.serverTimeoutObj)
      return this
    },
    start: function() {
      this.timeoutObj = setTimeout(function() {
        // 这里发送一个心跳,后端收到后,返回一个心跳消息,
        wsRef.current.send(heartParams)
        this.serverTimeoutObj = setTimeout(function() { // 如果超过一定时间还没重置,说明后端主动断开了
          wsRef.current.close()
        }, this.timeout)
      }, this.timeout)
    }
  }

  return [wsRef.current, wsData]
}

export default useWebSocket
import useWebSocket from './useWebSocket'
const [ws, wsData] = useWebSocket(wsUrl, { joinParams: '' })

useEffect(() => {
    console.log('webSocket message:', wsData)
}, [wsData])

const handleSendMessage = (params) => { // 向socket发送消息,格式为string
	ws.send(JSON.stringify(params))
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值