一、Web Work定义
TypeScript
复制代码
useEffect(() => {
let webSocketIndex = -1
const 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 的启动使用
TypeScript
复制代码
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) {
//初始化webSocket
case "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 消息队列实现)
TypeScript
复制代码
/**
* 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;
}
}