Files
video-create/web/client/src/lib/websocket.ts
sion123 7440ade66d feat(assets): 优化资产预览性能并添加资源管理器连接状态提示
- 使用缩略图替代原图展示,通过 sharp 库生成缓存缩略图
- 优化资产分组逻辑,避免不必要的重计算
- 添加 WebSocket 连接状态提示到输入框
- 使用 `useCallback` 和 `useRef` 优化组件渲染性能
- 添加 AbortController 支持请求取消,防止内存泄漏
- 添加 `disconnected` 事件处理,自动重置会话状态
2026-05-08 02:47:23 +08:00

61 lines
1.8 KiB
TypeScript

type MessageHandler = (data: Record<string, unknown>) => void;
class ChatSocket {
private ws: WebSocket | null = null;
private handlers: Map<string, MessageHandler[]> = new Map();
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
private intentionallyClosed = false;
connect() {
this.intentionallyClosed = false;
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const url = `${protocol}//${location.host}/ws`;
this.ws = new WebSocket(url);
this.ws.onopen = () => { this.emit('connected', {}); };
this.ws.onmessage = (event) => {
try { const { type, data } = JSON.parse(event.data); this.emit(type, data); } catch {}
};
this.ws.onclose = () => {
this.emit('disconnected', {});
if (!this.intentionallyClosed) {
this.reconnectTimer = setTimeout(() => this.connect(), 3000);
}
};
}
on(type: string, handler: MessageHandler) {
if (!this.handlers.has(type)) this.handlers.set(type, []);
this.handlers.get(type)!.push(handler);
}
off(type: string, handler: MessageHandler) {
const list = this.handlers.get(type);
if (list) {
const idx = list.indexOf(handler);
if (idx !== -1) list.splice(idx, 1);
}
}
send(type: string, data: Record<string, unknown> = {}) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type, ...data }));
}
}
stop() { this.send('stop'); }
private emit(type: string, data: Record<string, unknown>) {
(this.handlers.get(type) || []).forEach((h) => h(data));
}
disconnect() {
this.intentionallyClosed = true;
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
this.ws?.close();
this.ws = null;
}
}
export const chatSocket = new ChatSocket();