websocket-react使用

avatar
作者
猴君
阅读量: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; 

(占个坑,后续更新一下)

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!