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

2024-11-18 20:10:17 +0800 CST views 714

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

前言

使用AJAX和WebSocket都可以实现消息推送,但它们在实现方式和适用场景上有所不同。本文将对这两种技术的实现进行简要说明,并介绍如何封装一个WebSocket消息推送管理器,替代传统的AJAX轮询方式。

AJAX 实现消息推送

轮询(Polling)

轮询是指客户端定期向服务器发送请求以检查是否有新消息。尽管简单易用,但频繁的无效请求会带来性能开销。

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

// 开始轮询
pollForMessages();

长轮询(Long-Polling)

长轮询是轮询的改进版本,客户端发起请求后,服务器在有新消息时才会返回响应,否则保持连接。尽管能减少无效请求,但仍存在延迟问题。

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消息)送到不同的收件人(客户端)。你通过一辆智能快递车(WebSocket连接)传递消息,并记录每个收件人的信息。每次有新消息时,快递车会自动将包裹送达收件人,并在收到回复时立刻通知你。

WebSocketManager 设计思路

WebSocketMessenger负责管理和维护WebSocket连接,并通过封装实现对连接的控制、消息的发送和接收,以及重连机制。

WebSocketManager 类

class WebSocketManager {
  constructor(url = null, userId = null, receiveMessageCallback = null) {
    this.socket = null;
    this.sendTimeObj = null;
    this.reconnectTimeObj = null;
    this.reconnectTimeDistance = 5000;
    this.maxReconnectAttempts = 10;
    this.reconnectAttempts = 0;
    this.id = userId;
    this.url = url;
    this.receiveMessageCallback = receiveMessageCallback;
  }

  // 开启WebSocket连接
  async start() {
    if (this.url && this.id) {
      this.connectWebSocket();
    } else {
      console.error('WebSocket errors: 请传入连接地址和用户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++;
        this.reconnectTimeObj = setTimeout(() => {
          this.connectWebSocket();
        }, this.reconnectTimeDistance);
      } else {
        this.reconnectAttempts = 0;
        console.error('WebSocketManager errors: Max reconnect attempts reached.');
      }
    };

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

  // 发送消息
  sendMessage(message) {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(message);
    } else {
      console.error('WebSocketManager error: WebSocket connection is not open.');
    }
  }

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

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

使用Demo

在页面中可以这样使用该封装类:

<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>
        const receiveMessage = (res) => {
            console.log('接收消息回调:', res);
        };
        const socketManager = new WebSocketManager('ws://localhost:3000', 'userid292992', receiveMessage);
        socketManager.start();
    </script>
</head>

总结

与传统的AJAX轮询相比,WebSocket提供了更加高效的消息推送方式。通过封装一个WebSocket管理器,可以有效处理连接、消息传递和自动重连等操作,使开发过程更加简洁和灵活。

推荐文章

PyMySQL - Python中非常有用的库
2024-11-18 14:43:28 +0800 CST
使用Python提取图片中的GPS信息
2024-11-18 13:46:22 +0800 CST
windows安装sphinx3.0.3(中文检索)
2024-11-17 05:23:31 +0800 CST
css模拟了MacBook的外观
2024-11-18 14:07:40 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
PHP 代码功能与使用说明
2024-11-18 23:08:44 +0800 CST
ElasticSearch简介与安装指南
2024-11-19 02:17:38 +0800 CST
GROMACS:一个美轮美奂的C++库
2024-11-18 19:43:29 +0800 CST
Vue 3 中的 Fragments 是什么?
2024-11-17 17:05:46 +0800 CST
JavaScript 流程控制
2024-11-19 05:14:38 +0800 CST
html5在客户端存储数据
2024-11-17 05:02:17 +0800 CST
mysql int bigint 自增索引范围
2024-11-18 07:29:12 +0800 CST
JavaScript 上传文件的几种方式
2024-11-18 21:11:59 +0800 CST
php机器学习神经网络库
2024-11-19 09:03:47 +0800 CST
程序员茄子在线接单