websocket通信

看同事大佬封装的websocket,在这里记录一下,温故而知新,增加websocket.ts(websocket连接、失败、关闭操作文件),control.ts(发布订阅模式操作文件),index.ts

  1. websocket.ts
     1 import EventListenControl from './control'//引入发布订阅模式
     2 import {basePath,port,baseIp,webport} from '@/config/ip.config'
     3 const defaultURL = "ws://127.0.0.1:3006/ws";//websocket连接地址
     4 interface PrepareRequest {
     5     key: string;
     6     val:any;
     7 }
     8 //定义websocket类
     9 class Ws extends EventListenControl {
    10     url = "";//websocket地址
    11     ws: WebSocket | null = null;//websocket
    12     connected = false;//判断是否连接成功
    13     pending = false;//判断是否在连接中
    14     prepareList: PrepareRequest[] = [];//请求队列中的消息
    15     heartbeat: any = null;//判断是否已经存在请求通道
    16     loginApi: string;//登录api验证登录
    17     constructor(loginApi?: string, url = defaultURL) {
    18         super();
    19         this.url = url;
    20         this.loginApi = "";//默认没有使用接口验证
    21     }
    22     connect(params?: string) {//params传入的当前用户id
    23         setTimeout(() => {
    24             if (this.pending) return;
    25             this.pending = true;
    26             this.destroy();
    27             const url = this.url + (params ? '?id='+params : "");//判断params传入的当前用户id,存在就拼在地址后传入
    28             try {
    29                 let ws = new WebSocket(url);
    30                 this.ws = ws;
    31                 ws.onmessage = (event) => {//接收消息,收到消息后将消息广播出去(发布)
    32                     if (this.connected) {
    33                         let data = JSON.parse(event.data);
    34                         this.emit(data.key, data.val);//通过key来制定发布消息
    35                     }
    36                 }
    37                 ws.onopen = (e) => {
    38                     this.onconnect(e);
    39                     this.connected = true;
    40                     this.pending = false;
    41                 }
    42                 ws.onclose = e => {
    43                     if (ws === this.ws) {
    44                         this.pending = false;
    45                         this.connected = false;
    46                     }
    47                 }
    48                 ws.onerror = (e) => {
    49                     console.log('onerror执行error事件,开始重连');
    50                   }
    51             } catch (error) {
    52                 console.log(error);
    53             }
    54         }, 200)
    55     }
    56     postmessage(key : string, val: Object) {
    57         if (this.ws && this.connected) {//判断当前请求队列是否在使用或者websocket是否连接失败,如果失败就将消息先存到队列中,
    58             const dataString = JSON.stringify({
    59                 key,
    60                 val,
    61             })
    62             this.ws.send(dataString);
    63         } else {
    64             this.prepareList.push({ key,val });
    65         }
    66     }
    67     destroy() {
    68         if (this.ws) {
    69             this.ws.close();
    70         }
    71         if (this.heartbeat) {
    72             clearInterval(this.heartbeat);
    73             this.heartbeat = null;
    74         }
    75     }
    76     onconnect(e: Event) {
    77         if (!this.heartbeat) {
    78             this.heartbeat = setInterval(() => {
    79                 this.postmessage("heartbeat", "ping");
    80             }, 1000 * 60 * 2);
    81         }
    82         this.afterConnect(e);
    83     }
    84     afterConnect(e: Event) { }
    85 }
    86 
    87 const createWebsocket = (loginApi?: string,) => {
    88     let ws = new Ws();//可传入接口,也可不传入,传入接口为需要验证的接口
    89     return ws;
    90 }
    91 
    92 export {
    93     createWebsocket,
    94 };
    95 
    96 export default Ws;
  2. control.ts
    class EventListenControl {
        container: any = {};
        on(evt: string, callback: Function) {//订阅时,将对应方法和key值存储在container中
            if (!this.container[evt]) this.container[evt] = [];
            this.container[evt].push(callback);
        }
        emit(evt: string, ...arg: any[]) {//发布时,会去container中通过传入evt即key值来查找,找到后将数据传入订阅写的回调中
            if (this.container.hasOwnProperty(evt))
                this.container[evt].forEach((fn: Function) => {
                    fn(...arg);
                })
        }
        remove(evt: string, callback: Function) {//删除container中的订阅方法
            if (this.container[evt] && this.container[evt] instanceof Array) {
                let idx = this.container[evt].findIndex((el: Function) => el == callback);
                if (idx >= 0) {
                    this.container[evt].splice(idx, 1);
                }
            }
        }
    }
    
    export default EventListenControl;
  3. index.ts
    import { createWebsocket } from './websocket'
    const ws = createWebsocket();
    ws.onconnect = (e) => {};
    export default ws;
  4. vue3组件中调动,
    在test.vue组件中引入index.ts
    (1.)连接websocket
    <template>
    
    </template>
    
    <script lang="ts" setup>
    import { ref,onMounted } from "vue";
    import ws from './websocket/index'
    onMounted(()=>{
      ws.connect("123456465");//连接websocket,123456465为当前用户id
    })
    </script>
    
    <style lang="less" scoped>
    
    </style>

    (2.)订阅

    <template>
    
    </template>
    
    <script lang="ts" setup>
    import { ref,onMounted } from "vue";
    import ws from './websocket/index'
    //消息接收
    const handleReceiveMessage = (res: any) => {
        console.log(res,"接收到的消息")
    };
    ws.on("lalala", handleReceiveMessage);
    </script>
    
    <style lang="less" scoped>
    
    </style>

    (3.)发布

    <script lang="ts" setup>
    import { ref,onMounted } from "vue";
    import ws from './websocket/index'
    ws.emit("lalala","你好,请问你叫什么名字");
    </script>

    (4.)删除

    <script lang="ts" setup>
    import { ref,onMounted } from "vue";
    import ws from './websocket/index'
    ws.remove("lalala");
    </script>

    这是我在使用中用到的一些方法,对于其中的接口校验认证我还没有操作过,所以没有在这里记录。

posted @ 2022-07-08 16:45  奔跑的哈密瓜  阅读(280)  评论(0编辑  收藏  举报