websocket自动重连封装
前端代码封装
import { ref, onUnmounted } from 'vue' ; interface WebSocketOptions { url : string; protocols? : string | string[ ] ; reconnectTimeout? : number;
} class WebSocketService { private ws : WebSocket | null = null ; private callbacks : { [ key: string] : Function[ ] } = { } ; private reconnectTimeoutMs : number = 5000 ; constructor ( private options : WebSocketOptions) { } public open ( ) : void { this . ws = new WebSocket ( this . options. url, this . options. protocols) this . ws. addEventListener ( 'open' , this . handleOpen) ; this . ws. addEventListener ( 'message' , this . handleMessage) ; this . ws. addEventListener ( 'error' , this . handleError) ; this . ws. addEventListener ( 'close' , this . handleClose) ; } public close ( isActiveClose = false ) : void { if ( this . ws) { this . ws. close ( ) ; if ( ! isActiveClose) { setTimeout ( ( ) => this . reconnect ( ) , this . reconnectTimeoutMs) ; } } } public reconnect ( ) : void { this . open ( ) ; } public on ( event: 'message' , callback : ( data : any) => void ) : void ; public on ( event: 'open' | 'error' | 'close' , callback : ( ) => void ) : void ; public on ( event: string, callback : ( ... args: any[ ] ) => void ) : void { if ( ! this . callbacks[ event] ) { this . callbacks[ event] = [ ] ; } this . callbacks[ event] . push ( callback) ; } private handleOpen = ( ) : void => { console. log ( 'WebSocket连接已建立' ) ; if ( this . callbacks. open) { this . callbacks. open. forEach ( ( cb ) => cb ( ) ) ; } } ; private handleMessage = ( event: MessageEvent) : void => { console. log ( event, "event" ) ; const data = JSON . parse ( event. data) ; console. log ( 'WebSocket接收到消息:' , data) ; if ( this . callbacks. message) { this . callbacks. message. forEach ( ( cb ) => cb ( data) ) ; } } ; private handleError = ( error: Event) : void => { console. error ( 'WebSocket错误:' , error) ; if ( this . callbacks. error) { this . callbacks. error. forEach ( ( cb ) => cb ( error) ) ; } } ; private handleClose = ( ) : void => { console. log ( 'WebSocket连接已关闭' ) ; if ( this . callbacks. close) { this . callbacks. close. forEach ( ( cb ) => cb ( ) ) ; if ( ! this . options. reconnectTimeout) { this . reconnect ( ) ; } } } ; public send ( data: any) : void { if ( this . ws && this . ws. readyState === WebSocket. OPEN ) { this . ws. send ( JSON . stringify ( data) ) ; } else { console. warn ( '尝试发送消息时WebSocket未连接' ) ; } }
} export default function useWebSocket ( options : WebSocketOptions) { const wsService = new WebSocketService ( options) ; onUnmounted ( ( ) => { wsService. close ( true ) ; } ) ; return { open : wsService. open . bind ( wsService) , close : wsService. close . bind ( wsService) , reconnect : wsService. reconnect . bind ( wsService) , on : wsService. on . bind ( wsService) , send : wsService. send . bind ( wsService) } ;
}
组件中使用
<script setup lang="ts">
import { onMounted } from 'vue'
import useWebSocket from "@/utils/websocket";
const os = useWebSocket({ url: 'http://localhost:3000' })const onSend = () => {os.send({ text: '你好' })
}onMounted(async () => {os.open()os.on('message', (event) => {console.log(event, "event");})
});
</script>
后端代码封装
const express = require ( 'express' ) ;
const bodyParser = require ( 'body-parser' ) ;
const http = require ( 'http' ) ;
const WebSocket = require ( 'ws' ) ;
const cors = require ( 'cors' ) ;
const app = express ( ) ;
const server = http. createServer ( app) ; const corsOption = { origin : 'http://localhost:8088' , methods : [ 'GET' , 'POST' , 'PUT' , 'DELETE' ] , allowedHeaders : [ 'Content-Type' , 'Authorization' ] ,
} app. use ( cors ( corsOption) )
app. use ( bodyParser. json ( { limit : '100mb' } ) ) ;
app. use ( bodyParser. urlencoded ( { limit : '100mb' , extended : true } ) ) ;
const wss = new WebSocket. Server ( { server } ) ;
wss. on ( 'connection' , ( ws ) => { console. log ( '客户端已连接' ) ; ws. on ( 'message' , ( message ) => { console. log ( '收到消息:' , JSON . parse ( message) ) ; const postMsg = { msg : "你好" } ws. send ( JSON . stringify ( postMsg) ) ; } ) ; ws. on ( 'close' , ( ) => { console. log ( '客户端已断开连接' ) ; } ) ;
} ) ;
app. get ( '/' , ( req, res ) => { res. send ( 'WebSocket Server Running' ) ;
} ) ;
server. listen ( 3000 , ( ) => { console. log ( '服务器在 http://localhost:3000 运行' ) ;
} ) ;