img

vue使用websocket以及附带封装源码

2023-03-10 0条评论 1k次阅读 JavaScript


概念

WebSocket的定义

  WebSocket是html5提供的一种在单个TCP连接上进行双向通信的协议,解决了客户端和服务端之间的实时通信问题。浏览器和服务器只需完成一次握手,两者之间就可以创建一个持久性的TCP连接,此后服务器和客户端通过此TCP连接进行双向实时通信。

WebSocket的优点

  很多网站为了实现数据推送,所用的技术都是ajax轮询。轮询是在特定的时间间隔,由浏览器主动发起请求,将服务器的数据拉回来。轮询需要不断的向服务器发送请求,会占用很多带宽和服务器资源。WebSocket建立TCP连接后,服务器可以主动给客户端传递数据,能够更好的节省服务器资源和带宽,实现更实时的数据通讯。

1038427-20190508104500965-1818149905 _1_.png

使用ws

引入

import websocket from "@/common/websockets";

发送ws

sendMessage(){
  let type = 1;
  let data = {
    url: 213123
  }
  websocket.request(type,data)
},

初始化并调用ws

initMeeting(){
  websocket.initWebsocket(
    202303112000001,
    this.dealWithCallback,
    {
      role:21312321,
      is_test:111,
      watch:222,
      openid:this.$route.query.openid || this.$tools.getCookie('openid')
    }
  )
},
dealWithCallback(res){
  console.log(`res===>`, res)
},

封装代码

const config = {
  websocketHost: 'ws://xxx.xxx.com/ws'
}

const websocket = {
  host:"",
  container:null,
  meet:{
    id:'', // 会议id
    receive:null, // 回调函数
    params:{}
  },
  // 重连属性
  connect:{
    lock:false, // 加锁,重连期间,不重复链接
    time:2, // 重连时间,目前每2秒重连一次
    count:15, // 允许最大重连次数
    currentNumner:0, // 当前重连次数
    close:false // 是否关闭
  },
  // 重连定时器
  timer:{
    time:null,
    startTime:0
  },
  heart:{
    time:null,
    startTime:0,
    activity:false,
    ping:10
  }
}



// 初始化websocket
const initWebsocket = (meetId,receive,params) => {
  websocket.url = `${config.websocketHost}/${meetId}`;
  websocket.meet.id = meetId
  websocket.meet.receive = receive
  websocket.meet.params = params
  console.log( websocket.meet.params )
  websocket.container = new WebSocket(websocket.url)
  let needReConnect = true; // 报错是否需要重连
  websocket.container.onopen = () => {
    // 每次重连,取消锁
    websocket.connect.lock = false;
    this.$store.store.dispatch("setItem",{isConnect:true})
    clearWebSocketTime("timer");
    websocketRequest("meet_login",{...websocket.meet.params});
    webSocketHeart()
  }
  websocket.container.onmessage = (res) => {
    websocket.meet.receive && websocket.meet.receive(JSON.parse(res.data));
  }
  websocket.container.onerror = (err) => {
    if(needReConnect) {
      websocket.connect.lock = false;
      needReConnect = false;
      reConnectWebsocket();
    }
    console.error("websocket connect is error",err);
  }
  websocket.container.onclose = (err) => {
    console.error("websocket connect is close",err);
    if(err.type == 'login_failed') return;
    if(needReConnect) {
      websocket.connect.lock = false;
      needReConnect = false;
      reConnectWebsocket();
    }
  }


}

const clearWebSocketTime =  (key) => {
  websocket[key].startTime = 0;
  if(websocket[key].time) {
    clearTimeout(websocket[key].time);
    websocket[key].time = null;
  }
}
// 重连服务端
const reConnectWebsocket = () =>{
  if(websocket.connect.close || websocket.connect.lock) return;
  // if(websocket.connect.lock) return;
  console.log("reconnecting......")
  websocket.connect.lock = true;
  this.$store.store.dispatch("setItem",{isConnect:false})
  websocket.connect.currentNumner += 1;
  clearWebSocketTime("timer");
  // 判断是否达到重连最多次数
  if(websocket.connect.currentNumner > websocket.connect.count){
    console.log("重连失败,请刷新重试")
    return;
  }
  websocket.timer.startTime = Date.now();
  websocket.timer.time = setTimeout(()=>{
    initWebsocket(websocket.meet.id,websocket.meet.receive,websocket.meet.params);
  },websocket.connect.time * 1000);
}

// 心跳
const webSocketHeart = () => {
  clearWebSocketTime("heart")
  if(websocket.heart.activity) return;
  websocket.heart.startTime = Date.now();
  websocket.heart.activity = true;
  websocket.heart.time = setTimeout(()=>{
    websocket.heart.activity = false
    websocketRequest("meet_ping",{})
    webSocketHeart()
  },websocket.heart.ping * 1000);

}
// 发送消息
const sendMessage = (data) => {
  if(!websocket.container) {
    console.error("websocket is not connect!")
    return;
  }
  if(data.type !== "meet_ping") console.log(data)
  websocket.container.send(JSON.stringify(data));
}

// 发送websocket请求
const websocketRequest = (type,data) => {
  sendMessage({
    type,
    data
  })
}

// 关闭websocket
const websocketClose =  () => {
  websocket.container && websocket.container.close()
  websocket.connect.close = true;
  setTimeout(()=>{  websocket.connect.close = false;},2000)
  websocket.container = null;
}

export default {
  request:websocketRequest,
  initWebsocket,
  sendMessage,
  close:websocketClose
}
🏷️ #ws#长连接

💬 COMMENT


🦄 支持markdown语法

👋友