网络编程
位置:首页>> 网络编程>> JavaScript>> 一文详解websocket在vue2中的封装使用

一文详解websocket在vue2中的封装使用

作者:梓恒  发布时间:2024-05-02 17:08:54 

标签:vue2,websocket,封装

websocket在vue2中的封装使用

先说需求: 页面中有websocket连接,进入的时候发送参数到后端,后端发送消息, 离开页面时发送参数至后端,后端停止发送消息,不得断开连接, 下一次进入时页面时不用再次连接。

实现思路:

  • 因为是全局连接一个websocket,所以这里采用单例模式

  • 也是因为封装的原因,页面中肯定是直接拿不到onmessage中返回的数据, 所以这里采用发布订阅模式来做

完整代码在最后,不想看我废话的可以直接扒拉了

步骤

步骤就是: 连接,页面发送消息,接收消息,over ~

首先定义连接websocket的方法

export default class SocketService {
    constructor(url){
        this.url = url
    },
    connect() {
        //判断浏览器是否支持websocket
        if (!window.WebSocket) {
          return console.log("您的浏览器不支持WebSocket");
        }
        url,
       //连接websocket
        this.ws = new WebSocket(this.url);
        //监听websocket各种状态
        this.ws.onopen = () => {};
        this.ws.onclose = () => {};
        this.ws.onerror = () => {};
        this.ws.onmessage = (e) => {};
    }
}

我们先让socket连接上叭

export default class SocketService {
    constructor(url, againConnect = true){
        this.url = url
        this.againConnect = againConnect;
    },
      ws = null;         // 和服务端连接的socket对象
      url;               //地址
      againConnect;      //标识断开是否重连
      connected = false; // 标识是否连接成功
      sendRetryCount = 0; // 记录重试的次数
      connectRetryCount = 0; // 重新连接尝试的次数
    connect() {
        //判断浏览器是否支持websocket
        if (!window.WebSocket) {
          return console.log("您的浏览器不支持WebSocket");
        }
        url,
       //连接websocket
        this.ws = new WebSocket(this.url);
        //监听websocket各种状态
        this.ws.onopen = () => {
            //连接上后所有标识清零
            this.connected = true;
            this.connectRetryCount = 0;
        };
        this.ws.onclose = () => {
            //连接关闭
            this.connected = false;
            this.connectRetryCount++;
            if (this.againConnect) {
                //重连
                setTimeout(() => {
                  this.connect();
                }, 500 * this.connectRetryCount);
              } else {
                //不重连的操作
                 sessionStorage.clear();
                 localStorage.clear();
                 message.error("登录超时");
                 router.push("/");
              }
        };
        this.ws.onerror = () => {
            //连接失败
              this.connected = false;
              this.connectRetryCount++;
              if (this.againConnect) {
                setTimeout(() => {
                  this.connect();
                }, 500 * this.connectRetryCount);
              }
        };
        this.ws.onmessage = (e) => {
            console.log(e)
        };
    },
    unSubscribe() {}
    send(){
        //发送消息的方法
    }
}

那么我们要怎么给后端发送消息呢,发送了消息之后我们又该怎样才能在页面中接收到消息呢?

在send方法中接收一个回调函数,

在message中调用,

subscribeList = {}; //记载回调函数
idList = [];
send(data, callback) {
    //判断此时有没有ws
    if (!this.ws) {
      this.connect();
      this.send(data, callback);
    } else {
      // 判断此时此刻有没有连接成功
      if (this.connected) {
        this.sendRetryCount = 0;
        this.ws.send(JSON.stringify(data));
        if (data.type === "sub") {
          //存储id
          this.idList.push(data.id);
          //存储回调函数,
          if (!this.subscribeList[data.id]) {
            this.subscribeList[data.id] = [callback];
          } else {
            this.subscribeList[data.id].push(callback);
          }
        }
      } else {
        this.sendRetryCount++;
        setTimeout(() => {
          this.send(data, callback);
        }, this.sendRetryCount * 500);
      }
    }
  }
connect(){
    ......
    this.ws.onmessage = (e) => {
      let { payload, requestId, type } = JSON.parse(e.data);
      if (type === "error") {
        console.log("出错了");
      }
      if (this.subscribeList[requestId]) {
        if (type === "complete") {
          console.log("完成了");
        } else if (type === "result") {
          this.subscribeList[requestId].forEach((item) =>
            item.call(this, payload)
          );
        }
      }
    };
}
//销毁回调函数
  unSubscribe() {
    //停止消息发送
    this.idList.forEach((item) => {
      this.send({ id: item, type: "unsub" });
      delete this.subscribeList[item];
    });
    this.idList = [];
 }
  • sub标识发送消息, unsub标识停止发送消息

  • id为事件的标识符

现在解决了页面中接收消息的问题,那么怎么保证离开页面,回到页面,使用的是同一个websocket呢,如果实例化这个类的话,那么每次进入都会实例化SocketService,

es6的class中有取值函数和存值函数, 具体使用请看这里:

Class 的基本语法 - ES6 教程 - 网道 (wangdoc.com)

instance = null;
static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService(false);
    }
    return this.instance;
 }
  • 使用getter,来拿取class中的instance,拿取的时候设置拦截该行为,判断instance有没有值,没有值就实例化SocketService给instance,返回instance,

页面中使用方式

import SocketService from "@/websocket/websocket";
mounted() {
    this.ws = SocketService.Instance;
    this.ws.send(
      {
        id: "11111",
        topic: "/xxx/xxx",
        parameter: {},
        type: "sub",
      },
      this.Callback
    );
}
destroyed() {
    this.ws.unSubscribe();
},
methods:{
    Callback(data) {
          console.log(data);
    },
}

看到这里了,不妨给个小心心叭

在vue中的封装

export default class SocketService {
  constructor(againConnect = true, url) {
    this.url = url;
    this.againConnect = againConnect;
  }
  instance = null;  //页面中使用的SocketService实例
  ws = null; // 和服务端连接的socket对象
  url; //地址
  againConnect;     //断开是否重连
  connected = false; // 标识是否连接成功
  sendRetryCount = 0; // 记录重试的次数
  connectRetryCount = 0; // 重新连接尝试的次数
  //单例模式保证只有一个SocketService实例
  static get Instance() {
    if (!this.instance) {
        this.url = '......'
      this.instance = new SocketService(false, url);
    }
    return this.instance;
  }
  //  定义连接服务器的方法
  connect() {
    // 这里判断你的浏览器支不支持websocket
    if (!window.WebSocket) {
      return console.log("您的浏览器不支持WebSocket");
    }
    this.ws = new WebSocket(this.url);
    //连接上了
    this.ws.onopen = () => {
      this.connected = true;
      // 重置重新连接的次数
      this.connectRetryCount = 0;
    };
      //连接关闭了,设置标识值为false,
    this.ws.onclose = () => {
      this.connected = false;
      this.connectRetryCount++;
      if (this.againConnect) {
        setTimeout(() => {
          this.connect();
        }, 500 * this.connectRetryCount);
      } else {
        sessionStorage.clear();
        localStorage.clear();
        message.error("登录超时");
        router.push("/");
      }
    };
    this.ws.onerror = () => {
      console.log("socket连接失败");
      this.connected = false;
      this.connectRetryCount++;
      if (this.againConnect) {
        setTimeout(() => {
          this.connect();
        }, 500 * this.connectRetryCount);
      }
    };
    this.ws.onmessage = (e) => {
      let { payload, requestId } = JSON.parse(e.data);
      if (this.subscribeList[requestId]) {
          this.subscribeList[requestId].forEach((item) =>
            item.call(this, payload)
          );
        }
    };
  }
  //销毁回调函数
  unSubscribe() {
    //停止消息发送
    this.idList.forEach((item) => {
      this.send({ id: item, type: "unsub" });
      delete this.subscribeList[item];
    });
    this.idList = [];
  }
  subscribeList = {}; //记载回调函数
  idList = [];
  // 发送数据的方法
  send(data, callback) {
    //判断此时有没有ws
    if (!this.ws) {
      this.connect();
      this.send(data, callback);
    } else {
      // 判断此时此刻有没有连接成功
      if (this.connected) {
        this.sendRetryCount = 0;
        this.ws.send(JSON.stringify(data));
        if (data.type === "sub") {
          //存储id
          this.idList.push(data.id);
          //存储回调函数,
          if (!this.subscribeList[data.id]) {
            this.subscribeList[data.id] = [callback];
          } else {
            this.subscribeList[data.id].push(callback);
          }
        }
      } else {
        this.sendRetryCount++;
        setTimeout(() => {
          this.send(data, callback);
        }, this.sendRetryCount * 500);
      }
    }
  }
}

来源:https://juejin.cn/post/7207707775772917818

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com