如何使用 Server-sent Events 实现客户端与服务端的断线重连

Server-sent Events 是一种用于服务器向浏览器发送实时事件的技术,它可以实现服务端推送数据到客户端而不需要浏览器发起请求。使用 Server-sent Events 可以轻松地实现“客户端与服务端的断线重连”功能,本文将为大家详细介绍如何使用 Server-sent Events 实现此功能。

什么是 Server-sent Events

Server-sent Events 是通过 HTTP 协议实现的一种事件流机制。当服务器需要向浏览器发送实时事件时,它可以使用 Server-sent Events 向该浏览器创建一个持久连接。一旦建立连接,服务器可以以事件流的形式将数据推送给浏览器。

Server-sent Events 有以下几个特点:

  • 它是基于 HTTP 协议的,因此不需要额外的握手过程或协商。
  • 数据是通过文本流传输的,因此可以使用简单的文本格式来传递消息。
  • 浏览器可以保持持久连接,以便接收来自服务器的多个事件。
  • 与 WebSockets 不同,Server-sent Events 仅允许服务器向浏览器发送事件,而不允许浏览器向服务器发送事件。因此它更适用于服务器推送而不是双向通信。

如何使用 Server-sent Events 实现断线重连

为了实现“客户端与服务端的断线重连”功能,我们可以使用以下步骤:

  1. 在客户端创建一个 SSE 对象并建立连接。

    const sse = new EventSource('/api/sse');

    这里我们假设服务器的 SSE 接口为 /api/sse,并且服务器将以事件流的形式将数据推送给浏览器。

  2. 监听 SSE 对象的 open 事件。

    sse.addEventListener('open', () => {
      console.log('连接已经建立');
    });

    当 SSE 对象连接成功时,open 事件会触发。

  3. 监听 SSE 对象的 error 事件。

    sse.addEventListener('error', (e) => {
      console.log('连接已经断开,将在 5 秒钟后重新连接', e);
    
      setTimeout(() => {
        sse.close();
        sse = new EventSource('/api/sse');
      }, 5000);
    });

    当 SSE 对象连接出现错误时,error 事件会触发。在这种情况下,我们可以关闭现有的 SSE 对象,并在一段时间后重新建立连接。这里我们使用了 5 秒钟的间隔,但你可以根据实际需要来调整。

  4. 监听 SSE 对象的 message 事件。

    sse.addEventListener('message', (e) => {
      console.log('收到数据', e.data);
    });

    当服务器将数据推送给浏览器时,message 事件会触发。

至此,我们已经实现了“客户端与服务端的断线重连”功能。当连接中断时,我们将在一段时间后重新建立连接,并重新接收服务端发送的数据。

示例代码

以下是一个简单的示例代码,它演示了如何使用 Server-sent Events 实现断线重连功能:

<!DOCTYPE html>
<html>
<head>
  <title>Server-sent Events 示例</title>
</head>
<body>
  <h1>Server-sent Events 示例</h1>
  <hr>
  <p id="message"></p>
  <script>
    let sse = new EventSource('/api/sse');

    sse.addEventListener('open', () => {
      console.log('连接已经建立');
    });

    sse.addEventListener('error', (e) => {
      console.log('连接已经断开,将在 5 秒钟后重新连接', e);

      setTimeout(() => {
        sse.close();
        sse = new EventSource('/api/sse');
      }, 5000);
    });

    sse.addEventListener('message', (e) => {
      console.log('收到数据', e.data);
      document.getElementById('message').textContent = e.data;
    });
  </script>
</body>
</html>

在上面的示例中,我们使用了一个简单的 Express 服务来提供 SSE 接口:

const express = require('express');
const { Server } = require('http');
const { join } = require('path');

const app = express();
const server = Server(app);

app.use(express.static(join(__dirname, 'public')));

app.get('/api/sse', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  const intervalId = setInterval(() => {
    res.write(`data: ${JSON.stringify({ time: new Date().toISOString() })}\n\n`);
  }, 1000);

  req.on('close', () => {
    clearInterval(intervalId);
    res.end();
  });
});

server.listen(8080, () => {
  console.log('服务器已经启动');
});

该服务将每秒钟向浏览器发送一个包含当前时间戳的 JSON 对象。

总结

Server-sent Events 是一种实现服务端推送数据到客户端的技术,它可以轻松地实现“客户端与服务端的断线重连”功能。在本文中,我们介绍了 Server-sent Events 的基本原理和使用方法,并给出了一个简单的示例代码,希望可以对读者理解和使用此技术有所帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659287c5eb4cecbf2d74c70c


纠错
反馈