封装websocket

摘要

本文将介绍两种不同的WebSocket客户端封装方法:使用函数封装和使用类封装。我们将分析它们的实现方式、特点和适用场景,以及如何根据项目需求选择合适的封装方式。

1. 引言

WebSocket提供了全双工通信渠道,允许服务器主动发送信息给客户端。在实际开发中,封装WebSocket客户端可以简化开发流程,提高代码的可维护性和可复用性。

2. 函数封装:createWebSocket

createWebSocket函数是一种简单的封装方式,它通过接收必要的参数来创建和管理WebSocket连接。以下是其主要特点:

  • 简洁性:作为一个函数,它提供了一种快速且直接的方式来处理WebSocket连接。
  • 自动重连:实现了自动重连机制,能够在连接断开时尝试重新连接。
  • 心跳检测:通过定时发送心跳包来保持连接的活跃状态。
  • 灵活性:提供了发送消息和关闭连接的方法,使得调用者可以灵活地控制WebSocket的生命周期。

3. 类封装:WebSocketClient

WebSocketClient类提供了面向对象的方式来管理WebSocket连接,具有以下特性:

  • 封装性:将WebSocket的创建、管理和销毁封装在一个类中,提高了代码的模块化。
  • 状态管理:通过属性来管理WebSocket的状态,如是否在重连中、是否手动关闭等。
  • 错误处理:拥有错误消息队列,能够在连接失败时缓存消息,并在重连成功后发送。
  • 事件监听:定义了多种事件处理方法,如onopenonerroroncloseonmessage,使得状态变化更加可控。



export function createWebSocket(url, onOpen, onMessage) {
 if (!url) return;
 let canReconnect = true;
 // 避免重复连接
 let lockReconnect = false;
 let needReconnect = true;
 let ws = null;
 connect();
 heartCheck();

 // 连接服务端
 function connect() {
  ws = new WebSocket(url);
  ws.onopen = function () {
   if (onOpen) {
    onOpen();
   }
  };
  ws.onmessage = function (msg) {
   if (msg && msg.data) {
    let response = JSON.parse(msg.data);
    //console.log(response);
    if (onMessage) {
     onMessage(response);
    } else {
     canReconnect = false;
    }
   }
  };
  ws.onerror = function () {
   console.log("链接错误");
   reconnect();
  };
  ws.onclose = function () {
   console.log("close");
   if (!needReconnect) {
    ws.close();
   } else {
    reconnect();
   }
  };
 }
 // 重新连接服务端
 function reconnect() {
  if (!canReconnect || lockReconnect) {
   return;
  }
  console.log("reconnect", "reconnect");
  lockReconnect = true;
  setTimeout(function () {
   connect();
   lockReconnect = false;
  }, 5000);
 }
 // 保持心跳连接
 function heartCheck() {
  if (ws && ws.readyState === 1) {
   ws.send(
    JSON.stringify({
     id: new Date().getTime(),
     method: "PING",
    })
   );
  }
  setTimeout(function () {
   heartCheck();
  }, 15000);
 }
 // 发送websocket消息
 function sendMessage(message) {
  if (ws && ws.readyState === 1) {
   ws.send(message);
  } else {
   console.log("WebSocket is not open");
  }
 }
 // 关闭websocket连接
 function closeWs() {
  needReconnect = false;
  ws.close();
 }

 return {
  ws,
  sendMessage,
  closeWs,
 };
}

class WebSocketClient {
    // 要连接的URL
    url
    // 一个协议字符串或一个协议字符串数组。
    // 这些字符串用来指定子协议,这样一个服务器就可以实现多个WebSocket子协议
    protocols
    // WebSocket 实例
    ws
    // 是否在重连中
    isReconnectionLoading = false
    // 延时重连的 id
    timeId = null
    // 是否是用户手动关闭连接
    isCustomClose = false
    // 错误消息队列
    errorStack = []

 constructor(url, protocols) {
  this.url = url;
  this.protocols = protocols;
  this.ws = null;
  this.onOpen = null;
  this.onMessage = null;
  this.connect();
 }

 connect() {
  if ("WebSocket" in window) {
   // 实例化
   this.ws = new WebSocket(this.url, this.protocols);
   // 监听事件
   this.onopen();
   this.onerror();
   this.onclose();
  
  } else {
   console.log("你的浏览器不支持 WebSocket");
  }
 }
 // 监听成功
 onopen() {
  this.ws.onopen = () => {
    console.log(this.ws, "onopen");
    
   // 发送成功连接之前所发送失败的消息
   this.errorStack.forEach((message) => {
    this.send(message);
   });
   this.errorStack = [];
   this.isReconnectionLoading = false;
  };
 }

 // 监听错误
 onerror() {
  this.ws.onerror = (err) => {
   console.log(err, "onerror");
   this.reconnection();
   this.isReconnectionLoading = false;
  };
 }

 // 监听关闭
 onclose() {
  this.ws.onclose = () => {
   console.log("onclose");
   // 用户手动关闭的不重连
   if (this.isCustomClose) return;
   this.reconnection();
   this.isReconnectionLoading = false;
  };
  }
  
   // 接收 WebSocket 消息
   async onmessage(fn) {
    this.ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data)
      fn(data )
      } catch (error) {
        console.log(error, 'error')
      }
    }
  }

  // 重连
  reconnection() {
    // 防止重复
    if (this.isReconnectionLoading) return
    this.isReconnectionLoading = true
    clearTimeout(this.timeId)
    this.timeId = setTimeout(() => {
      this.createWs()
    }, 3000)
  }

  // 发送消息
  send(message) {
    // 连接失败时的处理
    if (this.ws.readyState !== 1) {
//没有发送成功的信息保存下来,链接成功后重新发送
      this.errorStack.push(message)
      return
    }
    this.ws.send(message)
  }

  // 手动关闭
  close() {
    this.isCustomClose = true
    this.ws.close()
  }

  // 手动开启
  start() {
    this.isCustomClose = false
    this.reconnection()
  }


  // 销毁
  destroy() {
    this.close()
    this.ws = null
    this.errorStack = null
    this.eventCenter = null
  }

}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值