vue3+ts发布订阅模式

此次项目在写即时通讯的时候需要使用到发布订阅模式,一下在记录下项目中使用的方法

1.创建ts文件夹,写如下代码

class EventListenControl {
    container: any = {};//创建对象
    on(evt: string, callback: Function) {//订阅(evt:需要监听的字段,callback:方法)
        if (!this.container[evt]) this.container[evt] = [];
        this.container[evt].push(callback);//每一次订阅,将键和方法存入对象中
    }
    emit(evt: string, ...arg: any[]) {//发布
        if (this.container.hasOwnProperty(evt))//在对象中找对应的键
            this.container[evt].forEach((fn: Function) => {//调用对象中的方法返回数据
                fn(...arg);
            })
    }
    remove(evt: string, callback: Function) {//销毁当前订阅
        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;

2.在websocket中数据返回时,根据返回的字段进行信息发布

import EventListenControl from './control'
import {webSocketApi} from "@/config/axios.config"
const defaultURL = webSocketApi;

interface PrepareRequest {
    key: string;
    val:any;
}

//封装ws
class Ws extends EventListenControl {
    url = "";//websocket地址
    ws: WebSocket | null = null;//websocket
    connected = false;//判断是否连接成功
    pending = false;//判断是否在连接中
    prepareList: PrepareRequest[] = [];//请求队列中的消息
    heartbeat: any = null;//判断是否已经存在请求通道
    loginApi: string;//登录api验证登录
    constructor(loginApi?: string, url = defaultURL) {
        super();
        this.url = url;
        // this.loginApi = loginApi;//这里注掉登录认证
        this.loginApi = "";
    }
    connect() {//启动websocket
        setTimeout(() => {
            if (this.pending) return;
            this.pending = true;
            this.destroy();
            const url = this.url;//websocket地址
            try {
                let ws = new WebSocket(url);
                this.ws = ws;
                ws.onmessage = (event) => {//接收websocket回传数据
                    if (this.connected) {
                        let data = JSON.parse(event.data);//数据结构成对象
                        this.emit(data.key, data.val);//data.key就是订阅传入的evt,data.content为数据
                    }
                }
                ws.onopen = (e) => {//连接成功
                    this.onconnect(e);
                    this.connected = true;
                    this.pending = false;
                }
                ws.onclose = e => {//关闭连接
                    if (ws === this.ws) {
                        this.pending = false;
                        this.connected = false;
                    }
                }
                ws.onerror = (e) => {//连接失败
                    console.log('onerror执行error事件,开始重连');
                  }
            } catch (error) {
                console.log(error);
            }
        }, 200)
    }
    postmessage(key : string, val: Object) {//外部调用的发送方法
        if (this.ws && this.connected) {//判断队列是否有数据在传输或者连接终端,没的话发送
            const dataString = JSON.stringify({
                key,
                val,
            })
            this.ws.send(dataString);
        } else {//有的话就存到队列中
            this.prepareList.push({ key, val });
        }
    }
    destroy() {//关闭websocket
        if (this.ws) {
            this.ws.close();
        }
        if (this.heartbeat) {
            clearInterval(this.heartbeat);
            this.heartbeat = null;
        }
    }
    onconnect(e: Event) {
        if (!this.heartbeat) {
            this.heartbeat = setInterval(() => {
                this.postmessage("heartbeat", "ping");
            }, 1000 * 60 * 2);
        }
        this.afterConnect(e);
    }
    afterConnect(e: Event) { }
}
//new websocket对象
const createWebsocket = (loginApi?: string,) => {
    // let ws = new Ws(loginApi);
    let ws = new Ws();
    return ws;
}

export {
    createWebsocket,
};

export default Ws;

3.项目中使用,项目中引入第一步ts文件

//订阅
ws.on("chat", receiveMessage);//"chat"为约定字段,这里代指聊天,receiveMessage为方法

//回调方法,消息接收
const handleReceiveMessage = (res: any) => {//websocket返回的数据这里只接受类型为chat的

};

 

posted @ 2022-06-16 17:03  奔跑的哈密瓜  阅读(617)  评论(0编辑  收藏  举报