websocket全局封装使用

本文介绍了如何使用WebSocketManager类创建WebSocket对象,实现心跳机制以避免断连,以及在接收到消息后的处理和重连策略。当连接关闭或达到最大重试次数时,会关闭连接并停止心跳。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WebSocketManager 组件介绍

WebSocketManager 是一个用于管理 WebSocket 连接的封装组件,旨在简化 WebSocket 的使用,提供连接管理、消息发送、断线重连、心跳机制等功能。通过该组件,开发者可以快速实现 WebSocket 通信,并处理常见的连接问题。

主要功能

连接管理:

支持创建 WebSocket 连接,并自动处理连接成功、失败和关闭事件。
提供手动关闭连接的方法,确保资源释放。

断线重连:

当连接意外断开时,自动尝试重连,支持设置最大重连次数和重连间隔。
避免因网络波动导致的连接中断问题。

心跳机制:

支持定时发送心跳消息,保持连接活跃,防止因长时间无通信而被服务器断开。
消息发送与接收:

提供 sendMessage 方法,确保在连接打开时发送消息。
支持自定义消息接收回调函数,方便处理服务器返回的数据。

错误处理:

捕获并记录 WebSocket 错误事件,便于排查问题。

使用场景

实时通信应用(如聊天室、在线协作工具)。
实时数据监控(如设备状态、报警信息推送)。
需要保持长连接的场景(如在线游戏、实时通知)。

  • 调用案例如下:

const socketManager = new WebSocketManager(‘ws://example.com/socket’, receiveMessage)
socketManager.start()
.then(() => { })
.catch(error => { })
})

export default class WebSocketManager {
	constructor(url = null, msg, receiveMessageCallback = null) {
		this.socket = null // WebSocket 对象
		this.pingTimeout = null // 心跳计时器
		this.reconnectTimeout = null // 重连计时器
		this.reconnectTime = 3000 // 重连间隔,单位:毫秒
		this.maxReconnectAttempts = 3 // 最大重连尝试次数
		this.reconnectAttempts = 0; // 当前重连尝试次数
		this.url = url // WebSocket 连接地址
		this.msg = msg // 发送的消息
		this.receiveMessageCallback = receiveMessageCallback // 接收消息回调函数
		this.isManualClose = false // 标记是否手动关闭连接
		this.messageQueue = []; // 消息队列,用于存储连接未打开时的消息
	}
	/**
		 * 启动 WebSocket 连接
		 * @returns {Promise<void>}
		 */
	start() {
		return new Promise((resolve, reject) => {
			if (this.url) {
				this.isManualClose = false;
				this.connectWebSocket(resolve, reject);
			} else {
				reject(new Error('WebSocketManager erros: 请传入连接地址'));
			}
		});
	}
	/**
	 * 创建 WebSocket 连接
	 * @param {Function} resolve Promise 的 resolve 回调
	 * @param {Function} reject Promise 的 reject 回调
	 */
	connectWebSocket(resolve, reject) {
		// 创建 WebSocket 对象
		this.socket = new WebSocket(this.url);

		// 处理连接打开事件
		this.socket.onopen = () => {
			console.log('连接成功');
			resolve(); // 连接成功,触发 Promise 的 resolve
			// 发送初始消息
			this.sendMessage(this.msg);
			// 发送队列中的消息
			this.messageQueue.forEach(message => this.sendMessage(message));
			this.messageQueue = []; // 清空队列
			// 启动心跳机制
			// this.startHeartbeat();
		};

		// 处理接收到消息事件
		this.socket.addEventListener('message', event => {
			this.receiveMessage(event)
		})

		// 处理连接关闭事件
		this.socket.onclose = event => {
			console.log('断线重连中·····', event);
			// 如果是手动关闭,则不重连
			if (this.isManualClose) {
				console.log('手动关闭连接,不重连');
				return;
			}
			// 清除定时器
			clearTimeout(this.pingTimeout)
			clearTimeout(this.reconnectTimeout)
			// 尝试重连
			if (this.reconnectAttempts < this.maxReconnectAttempts) {
				this.reconnectAttempts++
				this.reconnectTimeout = setTimeout(() => {
					this.connectWebSocket()
				}, this.reconnectTime)
			} else {
				// 重置重连次数
				this.closeWebSocket()
				console.error('已达到最大重新连接尝试次数。无法重新连接。')
			}
		}

		// 处理连接错误事件
		this.socket.onerror = (event) => {
			console.error('WebSocketManager error:', event);
			reject(event); // 连接失败,触发 Promise 的 reject
		};
	}
	/**
		 * 启动心跳机制
		 */
	startHeartbeat() {
		this.pingTimeout = setInterval(() => {
			// 发送心跳消息
			this.sendMessage('ping')
		}, 10000) // 每隔 10 秒发送一次心跳
	}

	/**
	 * 发送消息
	 * @param {String} message 消息内容
	 */
	sendMessage(message) {
		if (this.socket && this.socket.readyState === WebSocket.OPEN) {
			this.socket.send(message);
		} else {
			console.warn('WebSocket 连接未打开,消息加入队列');
			this.messageQueue.push(message); // 将消息加入队列
		}
	}
	/**
		 * 接收到消息
		 */
	receiveMessage(event) {
		// 根据业务自行处理
		// 传入回调函数自行处理
		this.receiveMessageCallback && this.receiveMessageCallback(event.data) // 修复
	}
	/**
		 * 关闭连接
		 */
	closeWebSocket() {
		this.isManualClose = true // 标记为手动关闭
		this.socket.close()
		// 清除定时器 重置重连次数
		clearTimeout(this.pingTimeout)
		clearTimeout(this.reconnectTimeout)
		this.reconnectAttempts = 0
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农突围NO.1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值