使用 Server-sent Events 实现在线协作客户端与服务端心跳同步

在现代的 Web 应用中,协作是一个非常重要的功能。Web 应用需要能够让多个用户同时在一个文档或者应用中工作。在这种情况下,服务器需要及时同步所有客户端的操作状态,以确保多个用户之间的同步。在许多情况下,这可以通过使用 Server-sent Events 来实现。在这篇文章中,我们将介绍如何使用 Server-sent Events 来实现在线协作客户端与服务器端心跳同步的功能。

什么是 Server-sent Events?

Server-sent Events(SSE)是一种 Web 技术,它允许 Web 服务器推送数据到客户端。这个数据是以文本的形式发送的,格式是纯文本,而不是像传统的 Websockets 那样使用二进制格式。这种技术的好处在于它比 Websockets 更简单,更易于实现。同时,由于使用了 HTTP 协议,因此 SSE 也比 Websockets 更容易在防火墙和代理中穿透。

在线协作的实现

在本文中,我们将使用 Server-sent Events 来实现一个在线协作的功能。我们将创建一个简单的应用程序,该应用程序允许多个用户同时编辑同一个文档。每当一个用户做出更改时,应用程序就会将这些更改发送到服务器,并将它们推送到所有其他已连接的客户端。这样,每个客户端都会看到文档的最新状态,并且所有客户端之间可以实现同步。

创建客户端

我们首先需要创建客户端应用程序。在我们的示例中,我们将使用 HTML、CSS 和 JavaScript 来创建一个简单的应用程序。该应用程序将包含一个文本区域,用户可以在其中编辑文本,并且将这些编辑结果发送到服务器上。这里是 HTML 文件的代码:

<!doctype html>
<html>
  <head>
    <title>在线协作</title>
    <style>
      #editor {
        width: 100%;
        height: 300px;
      }
    </style>
    <script src="/app.js"></script>
  </head>
  <body>
    <textarea id="editor"></textarea>
  </body>
</html>

这里我们引入了一个名为 app.js 的 JavaScript 文件,它将包含我们的客户端应用程序。

实现心跳同步

我们需要让客户端定期向服务器发送一个心跳请求来同步操作状态。服务器会定期发送一个 SSE 事件,表示客户端需要更新状态。我们可以在 JavaScript 中使用下面这个函数:

function startHeartbeat() {
  setInterval(function() {
    fetch('/heartbeat')
      .then(function(response) {
        if (response.status !== 200) {
          console.log('心跳请求失败!');
        }
      });
  }, 5000);
}

这个函数将每隔 5 秒钟向服务器发送一个心跳请求。如果请求不成功,函数会打印出错误信息。请注意,我们不需要从服务器获取任何数据,因为我们只是希望和服务器通信以同步状态。

实现服务器端

现在我们需要为服务器端创建代码。我们将创建一个 Node.js 应用程序来处理 SSE 事件和心跳请求。首先,在我们的 JavaScript 文件中,我们需要引入一些必要的库:

const http = require('http');
const fs = require('fs');
const url = require('url');
const path = require('path');
const {EventEmitter} = require('events');

然后,我们需要定义一些常量,用于存储文件路径和文件名:

const PUBLIC_PATH = path.join(__dirname, '..');
const INDEX_PATH = path.join(PUBLIC_PATH, 'index.html');
const PORT = process.env.PORT || 3000;

下一步,我们需要创建一个 ServerSentEvents 类,用于处理 SSE 事件和心跳请求:

class ServerSentEvents extends EventEmitter {
  constructor(req, res) {
    super();
    this.req = req;
    this.res = res;
    this.req.on('close', this.cleanup.bind(this));
    this.res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    });
  }

  send(event, data) {
    this.res.write(`event: ${event}\n`);
    this.res.write(`data: ${JSON.stringify(data)}\n\n`);
  }

  cleanup() {
    this.emit('end');
  }
}

这个类继承了 Node.js 内置的 EventEmitter,并处理了 SSE 事件和心跳请求。我们在每个 SSE 事件中发送一个事件名称和数据。在心跳请求中,我们只是返回一个空响应。

接下来,我们需要创建一个 HTTP 服务器,它将使用上面创建的类处理 SSE 事件和心跳请求。下面是服务器代码:

const server = http.createServer((req, res) => {
  const { headers, method, url } = req;
  const uri = url.parse(req.url).pathname;
  if (uri === '/') {
    fs.readFile(INDEX_PATH, (err, data) => {
      if (err) {
        res.writeHead(404);
        res.end('文件未找到');
      }
      res.writeHead(200);
      res.end(data);
    });
  }
  else if (uri === '/heartbeat') {
    res.writeHead(200);
    res.end();
  }
  else if (uri === '/events') {
    const sse = new ServerSentEvents(req, res);
    sse.send('connected', '连接建立完成!');
    sse.on('end', () => console.log('客户端连接已关闭。'));
  }
  else {
    res.writeHead(404);
    res.end('文件未找到');
  }
});

server.listen(PORT, () => {
  console.log(`服务器已在端口 ${PORT} 上运行`);
});

在这段代码中,我们首先处理了根路径的请求,以返回包含我们的应用程序的 HTML 文件。接下来,我们处理了心跳请求,直接返回一个空响应。然后,我们处理了 SSE 事件的请求,使用我们刚刚创建的 ServerSentEvents 类处理事件。最后,如果 uri 不匹配任何已知的路径,我们返回一个 404 错误。

在服务器上运行应用程序

现在我们可以在命令行中启动我们的服务器应用程序:

node app.js

在浏览器中访问 http://localhost:3000,打开我们的在线协作应用程序。当我们编辑文本时,客户端将会向服务器发送请求,并通过 SSE 事件接收更新状态的通知。同时,我们的 startHeartbeat 函数将会在后台发送心跳请求,在客户端和服务器之间保持连接活跃。

总结

在本文中,我们介绍了使用 Server-sent Events 实现在线协作客户端与服务端心跳同步的方法。我们创建了一个简单的应用程序,可以允许多个用户一起编辑同一个文档,并使用 Node.js 实现了 SSE 事件和一个心跳请求处理器。我们希望这篇文章能够帮助你了解如何使用 SSE 技术来实现复杂的 Web 应用程序。

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