SSE 实现的多房间聊天室的设计

阅读时长 7 分钟读完

在 Web 应用中,实现实时通信的需求越来越普遍。传统的 AJAX 请求方式存在频繁请求的问题,WebSocket 虽然解决了这个问题,但是需要服务器端的支持,并且可能会遇到防火墙等问题。这时候,Server-Sent Event(SSE)就成为了一种更为便捷的方式。

本文将介绍如何基于 SSE 实现一个多房间聊天室的设计。涉及的技术包括 HTML5 事件源、JavaScript 事件监听、Node.js 服务端等。文章将从以下几个方面进行阐述:

  1. 聊天室的实现方式
  2. 前端界面的设计
  3. 服务端的实现
  4. 代码实现

聊天室的实现方式

聊天室的核心功能是实时通信,而 SSE 正是为此而生的技术。SSE 允许浏览器客户端通过一个单向的连接,从服务器端获取实时信息。其工作原理是:客户端通过 EventSource 对象监听服务器端响应的事件源,服务器端会不断推送新的事件源,从而实现实时通信。

在聊天室中,我们可以将每个房间视为一个独立的事件源,客户端可以根据房间的不同,订阅不同的事件源。这样,当某个房间发送新的消息时,服务器端只需将该消息推送到对应的事件源中,客户端便能实时接收到消息。

前端界面的设计

聊天室的前端界面需要实现以下几个功能:

  1. 显示聊天记录
  2. 输入聊天内容
  3. 发送聊天内容
  4. 切换房间

其中,显示聊天记录的实现可以使用一个 DIV 元素,用来动态插入新的聊天记录。输入聊天内容可以使用一个文本框实现,发送聊天内容则需要在发送按钮上绑定一个 click 事件。切换房间可以使用一个下拉列表实现,通过切换列表项来订阅不同的事件源。

服务端的实现

在 Node.js 中,实现 SSE 的方式非常简单,只需要使用 res.write() 方法输出事件源即可。例如,下面的代码是一个简单的 SSE 服务端实现:

-- -------------------- ---- -------
----- ---- - ----------------

----------------------- ---- -- -
  ------------------ -
    --------------- --------------------
    ---------------- -----------
    ------------- ------------
  ---

  -------------- -- -
    ----- ---- - ------ ----- -------------
    ----------------
  -- ------
----------------

在上面的代码中,通过设置 Content-Type 为 text/event-stream,告知客户端该响应为 SSE 事件源。同时,设置 Cache-Control 为 no-cache 避免缓存,设置 Connection 为 keep-alive 保持连接。然后,通过 setInterval() 方法定时推送新的事件源。

代码实现

下面是一个基于 Node.js 和 SSE 的多房间聊天室的代码实现:

服务端代码

-- -------------------- ---- -------
----- ---- - ----------------
----- -- - --------------

----------------------- ---- -- -
  -- -------- -- ---- -
    ------------------ ---------------- --------------
    --------------------------------------------
  -
  ---- -- -------- -- ------------ -
    ------------------ ---------------- -------------------- ---------------- ----------- ------------- ---------------

    ----- ---- - --------------------------

    -------------- -- -
      ----- ---- - ------ ----- -------------
      ----------------
    -- ------
  -
----------------

在上面的代码中,通过判断请求的 URL,返回不同的响应。当 URL 为 / 时,返回 index.html 文件;当 URL 为 /chatroom 时,返回 SSE 事件源。同时,从请求头中获取房间号,在 setInterval() 方法中根据房间号推送不同的事件源。

客户端代码

-- -------------------- ---- -------
--------- -----
------
------
  ----- ----------------
  ----------- ------------
-------
------
  -------- ---------

  ---- ---------------------

  ------
    ------ ----------- --------------
    ------ ------------- ------------ -------------------------
    ------- --------- ------------------------
      ------- ------------------ ----------
      ------- ------------------ ----------
    ---------
  -------

  --------
    --- ------------

    -------- ------------------ -
      ----------- - --- ------------------------ --------- -------------- -----------------------------------------
      --------------------- - -------- ------- -
        ----- -------- - -------------------------------------
        ------------------ -- ---------- - --------
        ------------------ - ----------------------
      --
    -

    -------- ----------------- -
      -- ------------ -- ----- -
        --------------------
        ----------- - -----
      -
    -

    -------- ------------- -
      ----- ------- - -----------------------------------------
      -- -------- -- --- -
        ----- --- - --- -----------------
        ---------------- ------------ ------
        ------------------------------------ --------------------
        ------------------------------ -------------------------------------- -------- -----------
      -
    -

    -------- ------------ -
      ------------------
      -------------------
    -

    -------------------
  ---------
-------
-------

在上面的代码中,首先定义了一个全局变量 eventSource,用于存储事件源实例。在 startEventSource() 方法中,使用 EventSource 对象订阅 SSE 事件源,并在事件源接收到新的消息时,动态插入聊天记录。在 sendMessage() 方法中,通过 XMLHttpRequest 对象将聊天内容发送到服务器。在 changeRoom() 方法中,先停止当前的事件源,再订阅新的事件源。

总结

本文介绍了如何基于 SSE 实现一个多房间聊天室的设计。通过使用 HTML5 事件源和 JavaScript 事件监听技术,实现了一个简单的前端界面。同时,结合 Node.js 的 SSE 实现方式,实现了一个服务端。代码实现中,还介绍了如何根据房间号订阅不同的事件源。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f6bd31f6b2d6eab3f48b68

纠错
反馈