123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- class WebSocketClient {
- constructor() {
- this.ws = null;
- this.isConnected = false;
- this.reconnectAttempts = 0;
- this.maxReconnectAttempts = 5;
- this.reconnectInterval = 3000;
- this.messageQueue = [];
- this.onMessageCallback = null;
- this.onErrorCallback = null;
- this.onCloseCallback = null;
- this.onOpenCallback = null;
- this.url = null;
- this.heartbeatTimer = null;
- this.heartbeatInterval = 20000;
- this.heartbeatMessage = 'PING';
- this.lastHeartbeatTime = 0;
- this.heartbeatTimeout = 30000;
- this.connectionPromise = null;
- }
- connect(url, params = {}) {
- // 如果已经有正在进行的连接,返回该连接的Promise
- if (this.connectionPromise) {
- return this.connectionPromise;
- }
- this.connectionPromise = new Promise((resolve, reject) => {
- try {
- const queryString = Object.keys(params)
- .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
- .join('&');
- console.log(url,);
-
- const fullUrl = `${url}${queryString ? '?' + queryString : ''}`;
- this.url = fullUrl;
-
- this.ws = uni.connectSocket({
- url: fullUrl,
- success: () => {
- console.log('WebSocket连接成功');
- },
- fail: (error) => {
- console.error('WebSocket连接失败:', error);
- this.connectionPromise = null;
- reject(error);
- }
- });
- this.ws.onOpen(() => {
- console.log('WebSocket已打开');
- this.isConnected = true;
- this.reconnectAttempts = 0;
- this.startHeartbeat();
- // 发送队列中的消息
- while (this.messageQueue.length > 0) {
- const message = this.messageQueue.shift();
- this.send(message);
- }
- resolve();
- if (this.onOpenCallback) {
- this.onOpenCallback();
- }
- });
- this.ws.onMessage((res) => {
- if (res.data === 'PONG'||res.data === 'PING') {
- this.lastHeartbeatTime = Date.now();
- return;
- }
- if (this.onMessageCallback) {
- this.onMessageCallback(res.data);
- }
- });
- this.ws.onError((error) => {
- console.error('WebSocket错误:', error);
- this.isConnected = false;
- this.stopHeartbeat();
- if (this.onErrorCallback) {
- this.onErrorCallback(error);
- }
- this.connectionPromise = null;
- this.reconnect();
- });
- this.ws.onClose(() => {
- console.log('WebSocket已关闭');
- this.isConnected = false;
- this.stopHeartbeat();
- if (this.onCloseCallback) {
- this.onCloseCallback();
- }
- this.connectionPromise = null;
- this.reconnect();
- });
- } catch (error) {
- console.error('WebSocket初始化错误:', error);
- this.connectionPromise = null;
- reject(error);
- }
- });
- return this.connectionPromise;
- }
- startHeartbeat() {
- this.stopHeartbeat();
- this.lastHeartbeatTime = Date.now();
- this.heartbeatTimer = setInterval(() => {
- if (this.isConnected) {
- // 检查上次心跳响应时间
- if (Date.now() - this.lastHeartbeatTime > this.heartbeatTimeout) {
- console.log('心跳超时,准备重连');
- this.reconnect();
- return;
- }
- // 发送心跳
- this.send(this.heartbeatMessage);
- } else {
- this.stopHeartbeat();
- }
- }, this.heartbeatInterval);
- }
- stopHeartbeat() {
- if (this.heartbeatTimer) {
- clearInterval(this.heartbeatTimer);
- this.heartbeatTimer = null;
- }
- }
- reconnect() {
- if (this.reconnectAttempts < this.maxReconnectAttempts) {
- this.reconnectAttempts++;
- console.log(`尝试重新连接 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
- setTimeout(() => {
- this.connect(this.url); // 使用保存的URL进行重新连接
- }, this.reconnectInterval);
- }
- }
- async send(message) {
- // 如果未连接,将消息加入队列并尝试连接
- if (!this.isConnected) {
- this.messageQueue.push(message);
- if (!this.connectionPromise) {
- try {
- await this.connect(this.url);
- } catch (error) {
- console.error('发送消息时连接失败:', error);
- return;
- }
- }
- return;
- }
- // 确保连接已建立
- if (this.connectionPromise) {
- try {
- await this.connectionPromise;
- } catch (error) {
- console.error('等待连接建立失败:', error);
- return;
- }
- }
- // 发送消息
- this.ws.send({
- data: message,
- fail: (error) => {
- console.error('发送消息失败:', error);
- this.messageQueue.push(message);
- // 如果发送失败,可能是连接已断开,尝试重连
- if (!this.isConnected) {
- this.reconnect();
- }
- }
- });
- }
- close() {
- this.stopHeartbeat();
- if (this.ws) {
- this.ws.close();
- this.ws = null;
- this.isConnected = false;
- }
- }
- onMessage(callback) {
- this.onMessageCallback = callback;
- }
- onError(callback) {
- this.onErrorCallback = callback;
- }
- onClose(callback) {
- this.onCloseCallback = callback;
- }
- onOpen(callback) {
- this.onOpenCallback = callback;
- }
- }
- export default new WebSocketClient();
|