将WebSocket封装成一个可重连的Class
在现代的Web应用中,WebSocket已经成为了一种常见的协议,用于在客户端和服务器之间建立持久性的双向通信。然而,WebSocket连接可能会因为各种原因(如网络不稳定、服务器重启等)而断开。为了提高应用的稳定性和用户体验,我们需要一种机制来在连接断开时自动重连。本文将介绍如何将WebSocket封装成一个可重连的Class,以便在项目中方便地使用。
WebSocket基础
首先,让我们简要回顾一下WebSocket的基础。WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许服务器主动向客户端发送消息,这与传统的HTTP请求-响应模式不同。WebSocket连接在建立时会进行一次握手,然后保持连接直到客户端或服务器决定关闭它。
在JavaScript中,我们可以使用原生的WebSocket
API来创建和管理WebSocket连接。这个API提供了一些事件和方法,如onopen
、onmessage
、onclose
、onerror
和send
,用于处理连接的生命周期和发送/接收消息。
封装WebSocket Class
为了将WebSocket封装成一个可重连的Class,我们需要考虑以下几个方面:
- 连接管理:我们需要跟踪WebSocket连接的状态,并在必要时尝试重新连接。
- 事件处理:我们需要提供一种机制来让使用者注册和处理WebSocket事件(如打开、关闭、错误和消息)。
- 重连策略:我们需要定义一种策略来决定何时以及如何进行重连。
下面是一个简单的示例,展示了如何封装WebSocket Class:
class ReconnectingWebSocket { constructor(url, reconnectInterval = 1000) { this.url = url; this.reconnectInterval = reconnectInterval; this.ws = null; this.eventHandlers = { open: [], message: [], close: [], error: [], }; this.initConnection(); } initConnection() { this.ws = new WebSocket(this.url); this.ws.onopen = () => { this.handleEvent('open'); }; this.ws.onmessage = (event) => { this.handleEvent('message', event); }; this.ws.onclose = () => { this.handleEvent('close'); this.reconnect(); }; this.ws.onerror = (error) => { this.handleEvent('error', error); }; } handleEvent(eventType, event) { const handlers = this.eventHandlers[eventType]; handlers.forEach((handler) => handler(event)); } on(eventType, handler) { this.eventHandlers[eventType].push(handler); } off(eventType, handler) { const handlers = this.eventHandlers[eventType]; const index = handlers.indexOf(handler); if (index !== -1) { handlers.splice(index, 1); } } send(data) { if (this.ws.readyState === WebSocket.OPEN) { this.ws.send(data); } else { console.warn('WebSocket connection is not open. Unable to send data.'); } } reconnect() { setTimeout(() => { if (this.ws.readyState === WebSocket.CLOSED) { console.log('Attempting to reconnect WebSocket...'); this.initConnection(); } }, this.reconnectInterval); } close() { if (this.ws) { this.ws.close(); } } }
这个ReconnectingWebSocket
Class封装了原生的WebSocket API,并提供了以下功能:
- 通过
on
和off
方法注册和注销事件处理程序。 - 通过
send
方法发送消息。 - 在连接关闭时自动尝试重新连接。
- 提供了一个
close
方法来手动关闭连接。
使用封装后的WebSocket Class
使用ReconnectingWebSocket
Class很简单。下面是一个示例,展示了如何在项目中使用这个Class
const ws = new ReconnectingWebSocket('wss://example.com/ws'); ws.on('open', () => { console.log('WebSocket connection opened.'); ws.send('Hello, server!'); }); ws.on('message', (event) => { console.log('Received message:', event.data); }); ws.on('close', () => { console.log('WebSocket connection closed.'); }); ws.on('error', (error) => { console.error('WebSocket error:', error); });
在这个示例中,我们首先创建了一个新的ReconnectingWebSocket
实例,并指定了要连接的WebSocket服务器的URL。然后,我们使用on
方法注册了几个事件处理程序,分别用于处理连接打开、接收消息、连接关闭和错误事件。最后,我们在连接打开时发送了一条消息给服务器。
如果WebSocket连接因为某种原因断开了,ReconnectingWebSocket
Class会自动尝试重新连接,并在连接重新打开后继续发送和接收消息。
另一个版本的完整封装
1.定义一个websocket类
/* * 1.没连接到ws服务器的时候要不停的重连 * 2.重连的时候保证实例只有一个通道 */ import {Message} from 'element-ui' //params:{ // path:string//sw地址 // onmessage:function //} export class WhrWebSocket { constructor(params) { //只有params这个参数必须卸载constructor方法里,其他的实例属性可以写在外面 // 比如 socket = null this.socket = null this.params = params this.j = 0 //websocket重连次数 this.i = 0//发送信息次数 if ('WebSocket' in window) { this.init(params) } else { Message({ message: "浏览器不支持,请换浏览器再试", type: "error" }); } } init(params) { console.log("init方法开始") if (params.path) { this.path = params.path } else { throw new Error('参数socket服务器地址path必须存在') } this.socket = new WebSocket(this.path) this.socket.onopen = () => { console.log("连接开启") } this.socket.onclose = () => { this.j = 0 console.log("连接关闭") this.reconnect() } this.socket.onerror = () => { this.j = 0 console.log("连接错误") } this.socket.onmessage = params.onmessage || this.getMessage } getMessage(msg) { console.log("收到的消息", msg) return msg } send(data) { let s = null try { if (this.socket.readyState == 1) { this.i = 0 clearTimeout(s) this.socket.send(data) console.log("发送成功" + data) } else { if (this.i <= 10) { console.log(this.socket.readyState) ++this.i // this.send(data) s = setTimeout(() => { this.send(data) }, 100 * this.i) } else { this.i = 0 clearTimeout(s) } } } catch (e) { console.log(e) } } close() { clearTimeout(this.time) this.socket.close(1000, '手动关闭') console.log("调用关闭") } reconnect() { this.j++ //1.开始重连 //2.如果连接不成功要继续重连 if(this.j>1){ return; }else { if (this.socket.readyState == 1 || this.socket.readyState == 0) { // this.lock = false // clearTimeout(s) return false } else { console.log('开始重连') this.time = setTimeout(() => { this.init(this.params) }, 5000) } } } }
2.用法
//创建 this.socket = new WhrWebSocket({ path: this.path, onmessage: function (msg) { console.log(msg) }) //手动关闭 this.socket.close()