在本文中,让我们使用一种称为服务器发送事件 (SSE) 的技术构建一个简单的 node.js 数据流端点。我们将看到如何在没有任何外部库(甚至不是 Express.js)但仅使用 Node.js 的核心模块的情况下编写一个简单的 SSE 端点。
我们还将了解 SSE 实际上是什么,我们可以在哪些场景中使用它以及它与 WebSockets 有何不同,我们还将研究使用 SSE 技术带来的一些限制。
所以,事不宜迟,让我们直接进入。
背景:
服务器发送事件是服务器向其客户端发送更新的一种机制。通过更新,我们指的是新信息可用时。这里需要注意的重要一点是 SSE 是单向的。数据流的数据方向只是从服务器到客户端。另一种方式是不可能的。
如果您需要双向流,那么网络套接字将是最好的处理方式。在本文中,我们将只关注 SSE。
让我们简要地看一下为 SSE 铺平道路的两种基本方法:
短轮询:
检查服务器是否有新信息的最基本和低效的方法是对其进行短轮询。通过这种技术,我们不断地从客户端以较短的时间间隔向特定端点发出请求,以接收新信息。
一个基本的例子如下:
让 tickerData = null;const fetchTickerValue = async() => { try { const response = await fetch('https://api.server.com/ticker'); const data = await response.json(); tickerData = 数据; } catch (error) { console.error(error?.message ?? "ticker call failed"); } }setInterval(() => fetchTickerValue(), 2000);
长轮询:
正如我们在上面的例子中看到的,短轮询很快就会变得昂贵,因为每次向服务器发出新请求时,它也会涉及网络开销,例如每个请求的 TCP 握手。
长轮询改进了上述方法,使与服务的连接保持活动状态,直到服务器响应新数据。收到响应后,才建立新的连接。因此,我们不必像在短轮询代码示例中那样每两秒对服务器执行一次 ping 操作。
让 tickerData = null;const fetchTickerValue = async() => { try { const response = await fetch('https://api.server.com/ticker'); const data = await response.json(); tickerData = 数据; } catch (error) { console.error(error?.message ?? "ticker call failed"); } 最后 { fetchTickerValue(); } }
对于长轮询,我们必须牢记的一件事是服务器必须能够处理保持来自多个客户端的打开连接。此外,当谈到长轮询时,大部分实现细节都在服务器端。客户端的责任只是在先前打开的连接关闭后发起新的响应。
为了使长轮询有效,服务器需要知道请求的数据是否已在源处更改。它必须保持连接有效,直到检测到新的更改。当检测到变化时,它必须响应新数据并关闭连接。因此,与短轮询相比,网络开销可以大大减少。
服务器发送的事件:
现在,正如我们可能已经注意到的那样,轮询策略可能不是做事的最佳方法,尤其是当我们遇到这样一种情况,即服务器只需要按特定时间间隔向其客户端发送新信息,或者当其数据状态发生变化时.
这就是 SSE 成为一种更好的技术的地方。如果我们可以与服务器建立单向连接,而不是关闭连接只是为了立即重新打开它们,那会怎样呢?在客户端决定关闭它之前一直打开?简单来说,这就是 SSE 的大部分内容。
SSE 流格式:
简而言之,我们可以将 SSE 背后的思想定义如下:
网络应用程序“订阅”服务器生成的更新流,每当发生新事件时,都会向客户端发送通知。
对于发送事件流的服务器,数据和响应必须采用非常特定的格式:
- 响应头的内容类型应该是
text/event-stream
. - 响应应包含一个
data
字段,后跟您要发送的消息,并且应始终以double carriage return
如下方式终止:
数据:示例消息/n/n
3. 可以通过单个事件从多个数据点发送数据,但每条消息都应该是一个带有data
键的值,除了最后一条消息外,每个数据都应该以一个回车符结束。最后一条消息应以双回车结束。例如:
数据:消息项 1/n 数据:消息项 2/n 数据:消息项 3/n/n
来自单个事件的这些多个数据然后可以由客户端解析以将它们拆分成单独的值并且可以被它们用于他们的需要。
上交所代码演示:
让我们快速构建一个演示服务器,通过服务器发送的事件技术流式传输事件,以及一个使用它的简单前端 Web 客户端。
我们将只使用 Node.js 的核心库,以保持简单。
服务器:
上述服务器代码通过 SSE 事件流传输近乎实时的数据。
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/294477.html