代码 WebSocket在消息推送中的应用代码

2024-11-18 21:46:05 +0800 CST views 600

封装WebSocket消息推送,干翻Ajax轮询方式

内容: 大厂技术  高级前端  Node进阶

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群


使用AJAX和WebSocket都可以实现消息推送,但它们在实现方式和适用场景上有所不同。下面是这两种技术的简要对比:

AJAX 实现消息推送

AJAX(Asynchronous JavaScript and XML)允许在不重新加载整个页面的情况下,与服务器进行数据交换。传统的AJAX并不直接支持实时消息推送,因为它基于请求-响应模式。为了模拟消息推送,通常使用轮询(polling)或长轮询(long-polling)技术。

轮询(Polling)

轮询是定期向服务器发送请求,以检查是否有新消息。这种方法简单但效率较低,因为即使没有新消息,也会频繁地发送请求。

function pollForMessages() {
    $.ajax({
        url: '/messages', // 假设这是获取消息的API端点
        method: 'GET',
        success: function(data) {
            // 处理接收到的消息
            console.log(data);
            
            // 每5秒轮询一次
            setTimeout(pollForMessages, 5000);
        },
        error: function() {
            // 处理请求失败的情况
            setTimeout(pollForMessages, 10000); // 等待更长时间后重试
        }
    });
}

// 开始轮询
pollForMessages();

长轮询(Long-Polling)

长轮询是轮询的一种改进方式。客户端发起一个请求到服务器,服务器保持这个连接直到有新消息到达或超时。这种方式减少了无效的请求,但仍然存在一定的延迟和资源浪费。

WebSocket 实现消息推送

WebSocket 提供了一个全双工的通信通道,允许服务器主动向客户端推送消息。一旦建立了WebSocket连接,服务器和客户端就可以随时向对方发送消息,而不需要像AJAX那样频繁地发起请求。

WebSocket 客户端实现

var socket = new WebSocket('ws://your-server-url');

socket.onopen = function(event) {
    // 连接打开后,向服务器发送消息
    socket.send('Hello Server!');
};

socket.onmessage = function(event) {
    // 收到服务器发来的消息时触发
    console.log('Received:', event.data);
};

socket.onerror = function(error) {
    // 处理错误
    console.error('WebSocket Error:', error);
};

socket.onclose = function(event) {
    // 连接关闭时触发
    console.log('WebSocket is closed now.');
};

WebSocket 服务器端实现

服务器端实现WebSocket通常依赖于特定的服务器软件或框架,如Node.js的ws库、Java的Spring WebSocket等。这些库或框架提供了处理WebSocket连接的API,可以在这些连接上发送和接收消息。


封装WebSocket的实现

想象一下,你是一位超级快递员,负责将WebSocket消息准确无误地送到指定的地址。这些包裹里装的是WebSocket消息,而你的任务是根据每个包裹上的useridurl信息,找到正确的收件人并将包裹送达。

WebSocketMessenger(快递服务公司)

  • 职责:建立和维护WebSocket连接。
  • 特点:采用单例模式,确保同一时间只有一个实例在运行,存储收件人(recipient)和地址(address)信息,提供发送消息(send_message)的方法。

快递员(WebSocket连接实例)

  • 职责:由WebSocketMessenger创建和管理,负责实际的消息传递工作,知道如何与指定的收件人通信(通过地址)。

代码实现

class WebSocketManager {
  constructor(url = null, userId = null, receiveMessageCallback = null) {
    this.socket = null; // WebSocket 对象
    this.sendTimeObj = null; // 发送信息给服务端的重复调用的时间定时器
    this.reconnectTimeObj = null; // 尝试链接的宏观定时器
    this.reconnectTimeDistance = 5000; // 重连间隔,单位:毫秒
    this.maxReconnectAttempts = 10; // 最大重连尝试次数
    this.reconnectAttempts = 0; // 当前重连尝试次数
    this.id = userId; // 用户ID
    this.url = url; // WebSocket 连接地址
    this.receiveMessageCallback = receiveMessageCallback; // 接收消息回调函数
  }

  /**
   * 开启WebSocket
   */
  async start() {
    if (this.url && this.id) {
      // 连接WebSocket
      this.connectWebSocket();
    } else {
      console.error('WebSocket erros: 请传入连接地址和用户id');
    }
  }

  /**
   * 创建WebSocket连接
   */
  connectWebSocket() {
    let id = `${this.id}-${Math.random()}`;
    this.socket = new WebSocket(this.url, id);

    this.socket.onopen = (event) => {
      this.startSendServe();
    };

    this.socket.onmessage = (event) => {
      this.receiveMessage(event);
    };

    this.socket.onclose = (event) => {
      clearTimeout(this.sendTimeObj);
      clearTimeout(this.reconnectTimeObj);
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        this.reconnectAttempts++;
        console.log('重试链接次数:' + this.reconnectAttempts);
        this.reconnectTimeObj = setTimeout(() => {
          this.connectWebSocket();
        }, this.reconnectTimeDistance);
      } else {
        this.reconnectAttempts = 0;
        console.error('WebSocketManager erros: Max reconnect attempts reached. Unable to reconnect.');
      }
    };

    this.socket.onerror = (event) => {
      console.error('WebSocketManager error:', event);
    };
  }

  /**
   * 发送给node的第一条信息
   */
  startSendServe() {
    this.sendMessage('hi I come from client');
  }

  /**
   * 发送消息
   * @param {String} message 消息内容
   */
  sendMessage(message) {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(message);
    } else {
      console.error('WebSocketManager error: WebSocket connection is not open. Unable to send message.');
    }
  }

  /**
   * 接收到消息
   */
  receiveMessage(event) {
    console.log('receiveMessage:', event.data);
    this.receiveMessageCallback && this.receiveMessageCallback(event.data);
  }

  /**
   * 关闭连接
   */
  closeWebSocket() {
    this.socket.close();
    clearTimeout(this.sendTimeObj);
    clearTimeout(this.reconnectTimeObj);
    this.reconnectAttempts = 0;
  }
}

使用示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Demo</title>
    <script src="./webSocketManager.js"></script>
    <script>
        console.log(WebSocketManager);

        /**
         * 接收消息回调
         */
        const receiveMessage = (res) => {
            console.log('接收消息回调:', res);
        };

        const socketManager = new WebSocketManager('ws://localhost:3000', 'userid292992', receiveMessage);
        socketManager.start();
    </script>
</head>
<body>
</body>
</html>

导入模块后即可使用。


总结

该WebSocket管理器能够处理连接建立、消息接收和重连等常见场景。具体的业务逻辑和错误处理可根据实际情况进行进一步优化。


复制全文 生成海报 Web开发 实时通信 前端技术 Node.js 编程

推荐文章

利用Python构建语音助手
2024-11-19 04:24:50 +0800 CST
JavaScript 实现访问本地文件夹
2024-11-18 23:12:47 +0800 CST
JavaScript数组 splice
2024-11-18 20:46:19 +0800 CST
CSS 中的 `scrollbar-width` 属性
2024-11-19 01:32:55 +0800 CST
使用Python提取图片中的GPS信息
2024-11-18 13:46:22 +0800 CST
Vue3中的响应式原理是什么?
2024-11-19 09:43:12 +0800 CST
rangeSlider进度条滑块
2024-11-19 06:49:50 +0800 CST
网络数据抓取神器 Pipet
2024-11-19 05:43:20 +0800 CST
Nginx负载均衡详解
2024-11-17 07:43:48 +0800 CST
Go 语言实现 API 限流的最佳实践
2024-11-19 01:51:21 +0800 CST
实现微信回调多域名的方法
2024-11-18 09:45:18 +0800 CST
前端代码规范 - 图片相关
2024-11-19 08:34:48 +0800 CST
Nginx 如何防止 DDoS 攻击
2024-11-18 21:51:48 +0800 CST
Golang在整洁架构中优雅使用事务
2024-11-18 19:26:04 +0800 CST
js生成器函数
2024-11-18 15:21:08 +0800 CST
Rust 并发执行异步操作
2024-11-18 13:32:18 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
Redis和Memcached有什么区别?
2024-11-18 17:57:13 +0800 CST
程序员茄子在线接单