TypeScript中实现WebSocket

1、WebsocketModel:

import { ChatMsgInterface } from "./ChatMsgInterface";
import { DataContentInterface } from "./DataContentInterface";
import { MsgActionEnum } from "../core/enums/MsgActionEnum";
import { config } from "../core/config/config";
import { StoreKey } from "../core/constants/StoreKey";

export class WebsocketModel {

    private static instance: WebsocketModel | null = null;
    private socket: WebSocket| undefined;
    private messageHandler: ((message: string) => void) | null = null;

    private constructor() {
    }

    public static getInstance(): WebsocketModel {
        if (!WebsocketModel.instance) {
            WebsocketModel.instance = new WebsocketModel();
        }
        return WebsocketModel.instance;
    }

    init() {
        if (this.socket != undefined) {
            return false;
        }
        console.log('初始化WebSocket开始');
        this.socket = new WebSocket(config.websocketUrl, []);
        console.log('WebSocket实例化完成');
        this.socket.onopen = this.onOpen.bind(this);
        this.socket.onmessage = this.onMessage.bind(this);
        this.socket.onclose = this.onClose.bind(this);
        console.log('初始化WebSocket完成');
    }

    private onOpen(event: Event) {
        console.log("WebSocket连接已打开");
        const userId = this.getUserId();
        if (userId === '') {
            console.log('请先登录');
            return;
        }
        let chatMsg: ChatMsgInterface = {
            senderId: userId,
            receiverId: null,
            msg: null,
            msgId: null
        };
        let dataContent: DataContentInterface = {
            senderId: userId,
            action: MsgActionEnum.CONNECT,
            chatMsg: chatMsg,
            extand: null
        };
        let message = JSON.stringify(dataContent);
        this.socket?.send(message);

        // 开启心跳
        this.keepalive();
    }

    private onMessage(event: MessageEvent) {
        const receiverMessage = event.data as string;
        console.log("收到消息:" + receiverMessage);
        if (this.messageHandler) {
            this.messageHandler(receiverMessage);
        }

        // 签收消息
        const msgId = JSON.parse(receiverMessage).chatMsg.msgId;
        let signMsg: DataContentInterface = {
            senderId: this.getUserId(),
            action: MsgActionEnum.SIGNED,
            chatMsg: null,
            extand: msgId
        };
        let signMessage = JSON.stringify(signMsg);
        console.log('签收消息', signMessage);
        this.sendMessage(signMessage);
    }

    private onClose(event: Event) {
        console.log("WebSocket连接已关闭");
        this.socket = undefined;
        // 如果前端检测到被关闭了,重新打开
        this.init();
    }

    public sendMessage(message: string) {
        // 如果连接已经关闭,重新连接
        if (this.socket?.readyState === WebSocket.OPEN) {
            this.socket.send(message);
            return;
        }
        // 如果连接已经关闭,重新连接并重发消息
        this.resendMessage(message);
    }

    private resendMessage(message: string) {
        this.init();
        setTimeout(() => {
            if (this.socket?.readyState === WebSocket.OPEN) {
                this.socket.send(message);
            }
        }, 1000);
    }

    public setMessageHandler(handler: (message: string) => void) {
        this.messageHandler = handler;
    }

    // 获取用户id
    private getUserId() {
        let userId = "";
        let userInfo = localStorage.getItem(StoreKey.USER_INFO);
        console.log('userInfo', userInfo);
        if (userInfo){
            userId = JSON.parse(userInfo)?.id;
        }
        return userId;
    }

    // 心跳
    private keepalive() {
        // 构建对象
        let dataContent: DataContentInterface = {
            senderId: this.getUserId(),
            action: MsgActionEnum.KEEPALIVE,
            chatMsg: null,
            extand: null
        };

        let self = this;
        setInterval(function () {
            if (self.socket?.readyState === WebSocket.OPEN) {
                // 发送心跳
                let message = JSON.stringify(dataContent);
                self.socket?.send(message);
            }
        }, 5000);
    }
}
2、ChatMsgInterface:
export interface ChatMsgInterface {
    senderId: string | null;		// 发送者的用户id
    receiverId: string | null;		// 接受者的用户id
    msg: string | null;				// 聊天内容
    msgId: string | null;			// 用于消息的签收
}

3、DataContentInterface:

import type {ChatMsgInterface} from "./ChatMsgInterface";

export interface DataContentInterface {
    senderId: string;      // 发送者id
    action: number;    // 动作类型
    chatMsg: ChatMsgInterface | null;   // 用户的聊天内容entity
    extand: string | null;     // 扩展字段
}
4、MsgActionEnum:
export enum MsgActionEnum {
    CONNECT = 1, // 1, "第一次(或重连)初始化连接"
    CHAT = 2, // "聊天消息"
    SIGNED = 3, //"消息签收"
    KEEPALIVE = 4, // "客户端保持心跳"
    PULL_FRIEND = 5 // "拉取好友"
}

5、StoreKey:

export class StoreKey {
    static readonly USER_INFO: string = "user_info"
}

6、config:

const config = {
    websocketUrl: "wss://xxxx.xxxxx.com/ws"
}

export {
    config
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Vue3 使用 TypeScript 实现 WebSocket 单点登录,可以借助 `vue-cli` 脚手架工具和 `vuex` 状态管理库。 首先,在项目安装 `ws` 和 `vuex` 依赖: ```bash npm install ws vuex --save ``` 然后,在 `src/store/index.ts` 文件定义 `WebSocketState` 接口和 `store`: ```typescript import { createStore } from 'vuex' interface WebSocketState { ws: WebSocket | null isLogin: boolean } const store = createStore<WebSocketState>({ state() { return { ws: null, isLogin: false } }, mutations: { setWebSocket(state, ws) { state.ws = ws }, setIsLogin(state, isLogin) { state.isLogin = isLogin } } }) export default store ``` 接下来,在 `src/main.ts` 文件创建 WebSocket 实例,并将其挂载到 Vuex 的 state : ```typescript import { createApp } from 'vue' import App from './App.vue' import store from './store' const ws = new WebSocket('ws://localhost:3000') // 监听 WebSocket 连接 ws.addEventListener('open', () => { console.log('WebSocket 连接成功') }) // 监听 WebSocket 消息 ws.addEventListener('message', event => { const message = JSON.parse(event.data) switch (message.type) { case 'login': // 服务端返回登录成功消息 store.commit('setIsLogin', true) break case 'logout': // 服务端返回退出登录消息 store.commit('setIsLogin', false) break } }) const app = createApp(App) // 将 WebSocket 实例保存到 Vuex 的 state store.commit('setWebSocket', ws) app.use(store) app.mount('#app') ``` 接下来,在组件使用 `useStore` hook 获取 Vuex WebSocket 实例,并进行登录操作: ```typescript import { defineComponent, onMounted } from 'vue' import { useStore } from 'vuex' export default defineComponent({ setup() { const store = useStore() onMounted(() => { const { ws } = store.state // 登录操作 ws?.send(JSON.stringify({ type: 'login', token: 'xxx' // 用户的 token })) }) return { // ... } } }) ``` 在组件,我们可以使用 `computed` 属性监听 `isLogin` 状态的变化,并根据需要进行页面跳转或其他操作: ```typescript import { computed } from 'vue' import { useStore } from 'vuex' import { useRouter } from 'vue-router' export default defineComponent({ setup() { const store = useStore() const router = useRouter() // 监听用户登录状态 const isLogin = computed(() => store.state.isLogin) // 跳转到登录页面 if (!isLogin.value) { router.push('/login') } return { // ... } } }) ``` 以上就是使用 TypeScript 实现 WebSocket 单点登录的基本步骤。需要注意的是,在使用 WebSocket 时需要处理异常情况,比如网络连接异常等。另外,在实际项目,还需要根据具体业务场景进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值