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

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

封装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管理器,可以有效处理连接、消息传递和自动重连等操作,使开发过程更加简洁和灵活。

推荐文章

如何在Vue中处理动态路由?
2024-11-19 06:09:50 +0800 CST
Vue3中的v-slot指令有什么改变?
2024-11-18 07:32:50 +0800 CST
markdowns滚动事件
2024-11-19 10:07:32 +0800 CST
开源AI反混淆JS代码:HumanifyJS
2024-11-19 02:30:40 +0800 CST
Go语言SQL操作实战
2024-11-18 19:30:51 +0800 CST
Nginx 跨域处理配置
2024-11-18 16:51:51 +0800 CST
Python Invoke:强大的自动化任务库
2024-11-18 14:05:40 +0800 CST
Plyr.js 播放器介绍
2024-11-18 12:39:35 +0800 CST
Elasticsearch 监控和警报
2024-11-19 10:02:29 +0800 CST
robots.txt 的写法及用法
2024-11-19 01:44:21 +0800 CST
Vue3中如何实现国际化(i18n)?
2024-11-19 06:35:21 +0800 CST
pin.gl是基于WebRTC的屏幕共享工具
2024-11-19 06:38:05 +0800 CST
Vue3中如何实现状态管理?
2024-11-19 09:40:30 +0800 CST
用 Rust 玩转 Google Sheets API
2024-11-19 02:36:20 +0800 CST
支付宝批量转账
2024-11-18 20:26:17 +0800 CST
一个数字时钟的HTML
2024-11-19 07:46:53 +0800 CST
Vue 中如何处理父子组件通信?
2024-11-17 04:35:13 +0800 CST
Manticore Search:高性能的搜索引擎
2024-11-19 03:43:32 +0800 CST
程序员茄子在线接单