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
}