阅读量:2
问题
在一个应用中,如果需要在不同的组件之间共享同一个WebSocket连接,可以采用多种方法来实现。
比如:单例模式、全局变量、react context
React上下文(React Context)
如果你使用的是React,可以使用React Context来共享WebSocket连接。通过创建一个WebSocket上下文,可以在整个应用中提供和消费这个WebSocket连接。
// WebSocketContext.js import React, { createContext, useContext, useEffect, useState } from 'react'; const WebSocketContext = createContext(null); export const WebSocketProvider = ({ children }) => { const [socket, setSocket] = useState(null); useEffect(() => { const ws = new WebSocket('ws://example.com/socket'); setSocket(ws); return () => { ws.close(); }; }, []); return ( <WebSocketContext.Provider value={socket}> {children} </WebSocketContext.Provider> ); }; export const useWebSocket = () => { return useContext(WebSocketContext); }; // Component1.js import React from 'react'; import { useWebSocket } from './WebSocketContext'; const Component1 = () => { const socket = useWebSocket(); useEffect(() => { if (socket) { socket.addEventListener('message', handleMessage); } return () => { if (socket) { socket.removeEventListener('message', handleMessage); } }; }, [socket]); const handleMessage = (event) => { console.log('Message in Component 1:', event.data); }; return <div>Component 1</div>; }; export default Component1; // Component2.js import React from 'react'; import { useWebSocket } from './WebSocketContext'; const Component2 = () => { const socket = useWebSocket(); useEffect(() => { if (socket) { socket.addEventListener('message', handleMessage); } return () => { if (socket) { socket.removeEventListener('message', handleMessage); } }; }, [socket]); const handleMessage = (event) => { console.log('Message in Component 2:', event.data); }; return <div>Component 2</div>; }; export default Component2; // App.js import React from 'react'; import { WebSocketProvider } from './WebSocketContext'; import Component1 from './Component1'; import Component2 from './Component2'; const App = () => { return ( <WebSocketProvider> <Component1 /> <Component2 /> </WebSocketProvider> ); }; export default App;
实例
WebSocketContext.ts
// contexts/WebSocketContext.ts import React from 'react'; import WebSocketService from '../services/WebSocketService'; // 此处允许值为 null const WebSocketContext = React.createContext<WebSocketService | null>(null); export default WebSocketContext;
WebSocketService.ts
import { GetServerVersionResponse } from '@renderer/ipc/renderer_to_main_ipc_invoker/proxy/fpp' type CallbackFunction = (message: any) => void; type InvokeDevIpFilesResponse = { path: string folder: boolean } class WebSocketService { public static instance: WebSocketService; public ws: WebSocket; public listeners: Record<string, CallbackFunction[]>; public constructor(url: string) { this.ws = new WebSocket(url); this.listeners = {}; // 设置WebSocket事件监听器 this.ws.onmessage = this.handleMessage.bind(this); this.ws.onopen = this.handleOpen.bind(this); this.ws.onerror = this.handleError.bind(this); this.ws.onclose = this.handleClose.bind(this); } public static getInstance(url?: string): WebSocketService { if (!WebSocketService.instance) { if (!url) { throw new Error("WebSocketService instance has not been created yet. Please provide a URL."); } WebSocketService.instance = new WebSocketService(url); } return WebSocketService.instance; } public sendCommand(command: object): void { if (this.ws.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify(command)); } else { console.error('WebSocket is not open.'); } } public subscribe(command: string, callback: CallbackFunction): void { if (!this.listeners[command]) { this.listeners[command] = []; } this.listeners[command].push(callback); } public unsubscribe(command: string, callback: CallbackFunction): void { if (this.listeners[command]) { const index = this.listeners[command].indexOf(callback); if (index !== -1) { this.listeners[command].splice(index, 1); } } } //接收消息并处理 private handleMessage(event: MessageEvent): void { const message = JSON.parse(event.data); console.log(message) if ( message.version ) { this.triggerCallbacks('version', message); } else if(Array.isArray(message)){ const bagsList = message .filter(item => item.path && item.path.endsWith('.bag')) .map(item => item.path); if(bagsList){ this.triggerCallbacks('bags', message); } } // 其他消息类型 在这里添加类似的处理逻辑 } private triggerCallbacks(eventType: string, message: any): void { if (this.listeners[eventType]) { this.listeners[eventType].forEach((callback) => { callback(message); }); } } private handleOpen(): void { console.log('WebSocket connected.'); } private handleError(error: Event): void { console.error('❓ WebSocket error:', error); } private handleClose(): void { console.log('❌ WebSocket disconnected.'); } public close(): void { this.ws.close(); } public getGuiVersion(): Promise<string> { return new Promise((resolve, reject) => { const handleVersionMessage = (message: any) => { if (message.version) { resolve(message.version); this.unsubscribe('version', handleVersionMessage); } }; this.subscribe('version', handleVersionMessage); this.sendCommand({ command: 'version' }); setTimeout(() => { reject(new Error('Timeout waiting for GUI version.')); this.unsubscribe('version', handleVersionMessage); }, 5000); }); } public getBagsList(): Promise<InvokeDevIpFilesResponse[]> { return new Promise((resolve, reject) => { const handleBagsMessage = (message: any) => { console.log(message) resolve(message); this.unsubscribe('bags', handleBagsMessage); }; this.subscribe('bags', handleBagsMessage); const command = { command: 'bags', pattern: '*' }; this.sendCommand(command); setTimeout(() => { reject(new Error('Timeout waiting for bags list.')); this.unsubscribe('bags', handleBagsMessage); }, 5000); }); } public getMvizLink(): Promise<GetServerVersionResponse> { return new Promise((resolve, reject) => { const handleBagsMessage = (message: any) => { console.log(message) resolve(message); this.unsubscribe('bags', handleBagsMessage); }; this.subscribe('bags', handleBagsMessage); const command = { command: 'bags', pattern: '*' }; this.sendCommand(command); setTimeout(() => { reject(new Error('Timeout waiting for bags list.')); this.unsubscribe('bags', handleBagsMessage); }, 5000); }); } } export default WebSocketService;
App.js
// App.js 或其他顶层组件 import React from 'react'; import WebSocketContext from './contexts/WebSocketContext'; import WebSocketService from './services/WebSocketService'; function App() { // 创建 WebSocketService 实例, 可以在这里传递你需要连接的WebSocket服务器的URL const webSocketInstance = WebSocketService.getInstance('ws://your-websocket-url'); return ( // 使用 WebSocketContext.Provider 包裹你的组件并传递 value <WebSocketContext.Provider value={webSocketInstance}> {/* 这里是其他组件 */} </WebSocketContext.Provider> ); } export default App;
// SomeComponent.jsx
// SomeComponent.jsx import React, { useContext } from 'react'; import WebSocketContext from './contexts/WebSocketContext'; function SomeComponent() { // 使用 useContext 钩子获取 WebSocketService 实例 const webSocket = useContext(WebSocketContext); // 接下来可以使用 webSocket 发送消息或订阅事件 // ... return ( // 组件的其余部分 ); } export default SomeComponent;
(占个坑,后续更新一下)