因项目需要,提前学了WebSocket,分享一些经验,也是做一个学习文档吧在这里。

1.介绍WebSocket

        首先WebScoket它是一种网络传输协议。

        http请求一般都是前端请求之后,后端推送数据给前端,否则无法拿到数据。WebSocket的出现就使得服务端可以主动推送消息给客户端,客户端也可以主动请求数据。网上很多聊天系统都用WebSocket来实现,我这边处理的需求是表格,实现上来说也都大同小异。

        总的来说,WebSocket就是做实时响应的一种工具。

2.实现

        直接讲实现吧,代码贴在这里。

class WebsocketConn {
  constructor(url, cb) {
    this.cb = cb;
    this.url = url
    this.ws = null;
    this.s=0  //检测错误重新连接次数
    this.isnor=true//标记字段,表明是否是正常的请求
    this.lockReconnect = false;  //避免ws重复连接
    this.timeout = 30000; // 心跳检测时间
    this.heartCheckTimer = null // 心跳检测定时器
    this.heartCheckServerTimer = null;
    this.timetag=null
  }

  heartCheckToReset() {
    clearTimeout(this.heartCheckTimer);
    clearTimeout(this.heartCheckServerTimer);
    return this;
  }

  heartCheckToStart() {
    this.heartCheckTimer && clearTimeout(this.heartCheckTimer);
    this.heartCheckServerTimer && clearTimeout(this.heartCheckServerTimer);
    this.heartCheckTimer = setTimeout(() => {
      //这里发送一个心跳,后端收到后,返回一个心跳消息,
      //onmessage 拿到返回的心跳就说明连接正常
      this.ws.send("天王盖地虎");
      console.log("天王盖地虎")
      this.heartCheckServerTimer = setTimeout(() => {//如果超过一定时间还没重置,说明后端主动断开了
        console.log("后端主动断开")
        this.isnor=false
        this.ws.close();     //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
      }, this.timeout)
    }, this.timeout)
  }

  create() {
    // console.log(this.url)
    try{
      if('WebSocket' in window){
        this.ws = new WebSocket(this.url);
        //console.log(this.ws)
      }
      this.initEventHandle();
    }catch(e){
      this.reconnect(this.url);
      console.log(e);
    }
  }

  initEventHandle() {
    // console.log(this.cb)
    const _this=this
    this.ws.onclose = (error) => {
      !this.isnor && this.reconnect(this.url);
      console.log("错误",error)
      console.log("websocket 连接关闭!"+ new Date().toLocaleString());
    };
    this.ws.onerror = (error) => {
      this.s++
      if(this.s<6){//错误连接次数小于6,尝试重连
        this.reconnect(this.url);
        this.isnor=false;//标记字段,不是正常的请求,是重新连接
      }else{//错误连接次数大于等于6
        this.isnor=true;//重新开始正常请求
        this.s=0;//错误次数重置为零
      }
      console.log("websocket 连接错误!"+this.s);
    };
    this.ws.onopen = () => {
      this.heartCheckToReset().heartCheckToStart();      //心跳检测重置
      this.s=0
      // console.log("websocket 连接成功!"+new Date().toLocaleString());
    };
    this.ws.onmessage = (event) => {    //如果获取到消息,心跳检测重置
      this.s=0
      // console.log('websocket订阅A'+event)
      _this.cb(event)
      if (event.data === '宝塔镇河妖') {
        this.heartCheckToReset().heartCheckToStart();
        return
      }
      
      // this.heartCheckToReset().heartCheckToStart();      //拿到任何消息都说明当前连接是正常的
      // this.cb();
      // console.log(event)
      // console.log("websocket 收到消息啦:" + event);
    };
  }

  reconnect() {
    console.log("重新连接")
    if(this.lockReconnect) return;
    this.lockReconnect = true;
    this.timetag && clearTimeout(this.timetag)
    this.timetag=setTimeout(() => {     //重连,设置延迟避免请求过多
      this.create(this.url);
      this.lockReconnect = false;
    }, 2000);
  }

  close() {
    this.ws.close();
    
  }
}

export default WebsocketConn

代码比较全,后续有时间的话我会再上一版精简的,更通俗简单一些的。

3.注意

        还有想说一点的是在学习的时候发现有的人将scoket.io 和ws、nodejs-websocket混为一谈。

        scoket.io:是对 WebSocket的封装,

        而ws和nodejs-websocket是WebSocket的库,如果是https那么对应的就是wss。

ps:如果要ws.send()一个对象记得转换成string类型,JSON.stringfy({XXX})

 


 简单版:

data中先定义WS地址

JS代码如下:

mounted() {
    setTimeout(() => {
      this.initSysWebsocket(); //开启连接WS
    });
  },
  methods: {
    async initSysWebsocket() {
      try {
        if ("WebSocket" in window) {
          console.log(this.wsUrl);
          // 正式环境参数
          this.websocket = new WebSocket(this.wsUrl); // 初始化
          console.log(this.websocket);
          this.initWebSocket();
        }
      } catch (e) {
        console.log("尝试创建连接失败");
        // 如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接
        this.reConnect();
      }
    },

    reConnect() {
      // 重连函数
      var that = this;
      if (this.isConnect) return;
      this.rec && clearTimeout(this.rec);
      // 延迟5秒重连  避免过多次过频繁请求重连
      this.rec = setTimeout(function () {
        that.createWebSocket();
      }, 5000);
    },
    initWebSocket() {
      this.isConnect = true;
      // 连接错误
      this.websocket.onerror = this.setErrorMessage;
      // 连接成功
      this.websocket.onopen = this.setOnopenMessage;
      // 收到消息的回调
      this.websocket.onmessage = this.setOnmessageMessage;
      // 连接关闭的回调
      this.websocket.onclose = this.setOncloseMessage;
      // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
      window.onbeforeunload = this.onbeforeunload;
    },

    setErrorMessage() {
      this.isConnect = false;
      // 调用重连函数
      this.reConnect();
      console.log(
        "WebSocket连接发生错误   状态码:" + this.websocket.readyState
      );
    },

    setOnopenMessage() {
      console.log("WebSocket连接成功    状态码:" + this.websocket.readyState);
      if (this.queryId) {
        // console.log(" WS this.queryId", this.queryId);
        this.websocket.send(
          JSON.stringify({
            groupId: this.queryId,
            identify: this.identifyItem,
            name: this.nameItem,
            objectAddress: this.objectAddressItem,
            pageNum: this.$store.state.taosStore.pageNum,
            pageSize: this.$store.state.taosStore.pageSize,
          })
        );
        this.queryId = "";
      } else {
        this.websocket.send(
          JSON.stringify({
            groupId: this.nodeCheck,
            identify: this.identifyItem,
            name: this.nameItem,
            objectAddress: this.objectAddressItem,
            pageNum: this.$store.state.taosStore.pageNum,
            pageSize: this.$store.state.taosStore.pageSize,
          })
        );
        // 非页码变化清空选中节点id
        if (!this.$store.state.taosStore.pageNum) {
          this.nodeCheck = "";
        }
      }
    },

    setOnmessageMessage(event) {
      // 根据服务器推送的消息做自己的业务处理
      var json = JSON.parse(event.data);
      // 获取标签数据
      var markerData = json;
      console.log("list数据", markerData);
      this.getList = markerData;
    },

    setOncloseMessage() {
      this.isConnect = false;
      // 重连
      this.reConnect();
      // console.log('connection closed (' + e.code + ')')
      console.log("WebSocket连接关闭    状态码:" + this.websocket.readyState);
    },

    onbeforeunload() {
      this.closeWebSocket();
    },

    closeWebSocket() {
      this.websocket.close();
    },

原理也非常简单,就是this.setOnopenMessage连接成功后给后端传递相应的参数,this.setOnmessageMessage收到消息后调后赋值就可以了。

Logo

前往低代码交流专区

更多推荐