一、Web Work定义
useEffect(() => {let webSocketIndex = -1const websocketWorker = new Worker(new URL('./websocketWorker.worker.ts?worker', import.meta.url),{type: 'module' // 必须声明模块类型});//初始化WEBSOCKET(多个服务器选择最快建立连接的一个)const urls = (import.meta.env.VITE_WEB_SOCKET).split(',');for(const url of urls) {this.works.websocketWorker.postMessage({type: "INIT_WEBSOCKET", payload: {url: url}});}websocketWorker.onmessage = (e) => {//接收子线程消息//接收连接打开消息if(e.data.type === "OPEN") {//这里通过变量改变只使用一次opne选择最快反馈的服务器if(webSocketIndex === -1) {webSocketIndex = e.data.index;websocketWorker.postMessage({type: "SELECT_SOCKET", payload:e.data.index});}}};return () => {if(websocketWorker ) {websocketWorker.postMessage({ type: "CLOSE_WEBSOCKET" });const str = setTimeout(() => {websocketWorker .terminate()clearTimeout(str);}, 500);}};}, []);
二、子线程中WebSocket 的启动使用
let socket: WebSocket | null = null;
let sockets: WebSocket[] = [];
let pingTimer: NodeJS.Timeout | null = null;self.onmessage = (e) => {const message = e.data as MessageData;//webSocket 子进程switch(message.type) {//初始化webSocketcase "INIT_WEBSOCKET":const ws = new WebSocket(message.payload.url);sockets.push(ws);ws.onopen = () => self.postMessage({ type: 'OPEN', index: sockets.indexOf(ws) });return "";case "SELECT_SOCKET":socket = sockets[message.payload];// 发送Ping帧(心跳检测)pingTimer = setInterval(() => {(socket as WebSocket).send(new Uint8Array([0x89, 0x00])); }, PING_TIME);//消息队列先进先出const queue = new WebSocketQueue(socket);queue.listen((msg) => {console.log('SOCKET:', msg.timestamp, msg.data);});//其他socket连接关闭节省资源const otherSocket = sockets.filter((_, index) => index !== message.payload);for(const other of otherSocket) {other.close();}return ""; case "CLOSE_WEBSOCKET":if(socket) (socket as WebSocket).close();if(pingTimer) clearInterval(pingTimer);return ""; default:return ""; }};
三、补充(WebSocket 消息队列实现)
/*** WebSocket消息队列,先进先出*/
export class WebSocketQueue {private queue: {data: any, timestamp: number}[] = [];private messageHandler?: (msg: {data: any, timestamp: number}) => void;constructor(socket: WebSocket) {socket.onmessage = (ev) => {this.queue.push({data: ev.data, timestamp: Date.now()});this.messageHandler?.(this.queue.shift()!); // FIFO处理};}// 注册消息处理器public listen(handler: (msg: {data: any, timestamp: number}) => void) {this.messageHandler = handler;}
}