首页 >web前端 >js教程 >服务器范围事件

服务器范围事件

尊渡假赌尊渡假赌尊渡假赌
尊渡假赌尊渡假赌尊渡假赌原创
2025-02-27 09:25:10869浏览

Server-sent Events

核心要点

  • 服务器发送事件 (SSE) 是一种利用流将数据和/或 DOM 事件从服务器推送到客户端的方法,非常适用于需要定期更新数据的情况,例如体育比分或股票行情。
  • 创建 EventSource 对象允许您订阅事件流,并能够处理打开、消息和错误事件。
  • 从服务器发送事件需要使用 Content-type 头部(值为 text/event-stream)和 UTF-8 字符编码来提供内容。服务器发送事件的语法包括数据、事件类型、事件标识符和重试间隔。
  • 事件处理可以使用 onmessage 函数(仅用于发送消息事件的应用程序),但 addEventListener 方法对于处理自定义事件更灵活。
  • 大多数现代浏览器(包括 Chrome、Firefox 和 Safari)都支持服务器发送事件 (SSE),但 Internet Explorer 不支持。对于需要支持所有浏览器的应用程序,WebSockets 或长轮询可能更合适。
  1. 简介
  2. 订阅流:EventSource 对象
  3. 从服务器发送事件
    1. 发送消息事件
    2. 发送自定义事件
    3. 使用重试间隔管理重新连接
    4. 使用 id 字段设置唯一标识符
  4. 处理事件
  5. 处理错误
  6. 浏览器实现差异
  7. 浏览器支持和回退策略

假设您国家的国家篮球队正在参加世界篮球锦标赛。您想关注比赛,但由于比赛时间与您的工作时间冲突,无法观看。

幸运的是,您的国家新闻服务拥有一个非常出色的 Web 开发团队。他们构建了一个体育信息滚动显示器,每当出现犯规或得分时都会更新。您访问一个 URL,更新就会直接推送到您的浏览器。当然,您会想知道他们是如何做到的。答案是:服务器发送事件。

服务器发送事件是一种使用流将数据和/或 DOM 事件从服务器推送到客户端的方法。它适用于股票行情、体育比分、航班追踪、电子邮件通知——任何需要定期更新数据的情况。

等等! 我听到您说,我们不能已经使用 XMLHttpRequest 或 WebSockets 来做到这一点吗?是的,可以。但是,这样做需要扩展这些对象来实现 EventSource 本身的功能。

服务器端注意事项

由于服务器发送事件是数据流,因此它们需要长期连接。您需要使用能够处理大量同时连接的服务器。当然,事件驱动服务器特别适合流式传输事件。这些包括 Node.js、Juggernaut 和 Twisted。对于 Nginx,可以使用 nginx-push-stream-module 模块。但是,服务器配置不在本文讨论范围之内,并且会因您使用的服务器而异。

让我们看看如何使用 EventSource 对象订阅流。然后,我们将看看如何发送和处理事件。

订阅事件流:EventSource 对象

创建 EventSource 对象很简单。

<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>

EventSource 构造函数最多接受两个参数:

  • 一个 URL 字符串(必需);以及
  • 一个 可选 的字典参数,用于定义 withCredentials 属性的值。

字典在语法上类似于对象,但它们实际上是具有定义的名称-值对的关联数据数组。在本例中,withCredentials 是唯一可能的字典成员。其值可以是 true 或 false。(要了解有关字典的更多信息,请参阅 Web IDL 规范。)

仅当需要用户凭据(cookie)的跨域请求时,才需要包含字典参数。到目前为止,没有浏览器支持跨域 EventSource 请求。因此,我们不会在示例中包含第二个参数。

当 EventSource 连接打开时,它将触发一个 open 事件。我们可以通过设置 onopen 属性来定义一个处理该事件的函数。

<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/');
evtsrc.onopen = function(openevent){
    // 连接打开时执行的操作
}</code>

如果我们的连接出现问题,将触发一个错误。我们可以使用 onerror 属性为这些事件定义一个处理程序函数。我们将在“处理错误”部分讨论一些错误事件的原因。

<code class="language-javascript">evtsrc.onerror = function(openevent){
    // 发生错误时执行的操作
}</code>

流式事件默认为消息事件。要处理消息事件,我们可以使用 onmessage 属性来定义一个处理程序函数。

<code class="language-javascript">evtsrc.onmessage = function(openevent){
    // 接收到消息事件时执行的操作
}</code>

我们还可以使用 addEventListener() 来监听事件。这是处理自定义事件的唯一方法,正如我们将在“处理事件”部分看到的那样。

<code class="language-javascript">var onerrorhandler = function(openevent){
    // 执行的操作
}
evtsrc.addEventListener('error',onerrorhandler,false);</code>

要关闭连接,请使用 close() 方法。

<code class="language-javascript">evtsrc.close();</code>

因此,我们创建了 EventSource 对象,并为打开、消息和错误事件定义了处理程序。但是,为了使此方法有效,我们需要一个流式传输事件的 URL。

从服务器发送事件

服务器发送事件是作为来自 URL 的流的一部分交付的文本片段。为了让浏览器将我们的数据视为流,我们必须:

  • 使用 Content-type 头部(值为 text/event-stream)来提供内容;
  • 使用 UTF-8 字符编码。

服务器发送事件的语法很简单。它由一个或多个冒号分隔的字段名称-值对组成,后跟一个换行符。字段名称可以包含四个可能的值之一。

  • data::要发送的信息。
  • event::正在分派的事件类型。
  • id::客户端重新连接时要使用的事件标识符。
  • retry::浏览器尝试重新连接到 URL 之前应经过多少毫秒。

其中,只有 data 字段是必需的。

发送消息事件

在此示例中,我们将发送一个事件来宣布我们的锦标赛比赛中哪些球队正在比赛。当浏览器接收到此文本时,它将分派一个消息事件。

<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>

data 字段的值将成为消息事件的 data 属性的值。如上所述,服务器发送事件默认为消息事件。但正如我们稍后将讨论的那样,我们还可以通过包含 event 字段来分派自定义事件。

我们还可以将几条数据作为单个事件发送。每块数据后面都应该跟着一个换行符(换行符、回车符或两者)。在这里,我们正在追加一个包含此游戏位置和出席人数的事件。

<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/');
evtsrc.onopen = function(openevent){
    // 连接打开时执行的操作
}</code>

对于此事件,data 属性的值将是:Air Canada CentrenToronto, Ontario, CanadanAttendance: 19,800。

请注意事件之间的空行。为了让客户端接收事件,事件后面必须跟一个空行。注释以冒号开头。

发送自定义事件

除非我们另行指定,否则事件的类型为消息。为此,我们需要包含一个 event 字段。在下面的示例中,我们将向我们的流中添加两个 startingfive 事件,并将我们的数据作为 JSON 格式的字符串发送。

<code class="language-javascript">evtsrc.onerror = function(openevent){
    // 发生错误时执行的操作
}</code>

在这里,我们需要监听 startingfive 事件而不是消息事件。但是,我们的 data 字段仍然会成为事件的 data 属性的值。

我们将在“处理事件”部分讨论 data 属性和 MessageEvent 接口。

管理连接和重新连接

现在,虽然服务器确实将事件推送到浏览器,但现实情况要细微一些。如果服务器保持连接打开,EventSource 请求将是一个扩展的请求。如果它关闭,浏览器将等待几秒钟,然后重新连接。例如,如果 URL 发送一个文件结束标记,则连接可能会关闭。

每个浏览器都设置了自己的默认重新连接间隔。大多数会在 3 到 6 秒后重新连接。但是,您可以通过包含 retry 字段来控制此间隔。retry 字段指示客户端在重新连接到 URL 之前应等待多少毫秒。让我们从上面的示例构建并更改我们的事件以包含 5 秒(5000 毫秒)的重试间隔。

<code class="language-javascript">evtsrc.onmessage = function(openevent){
    // 接收到消息事件时执行的操作
}</code>

事件流可以保持活动状态,只要客户端已连接即可。根据您的架构和应用程序,您可能希望服务器定期关闭连接。

使用 id 字段设置唯一标识符

当浏览器重新连接到 URL 时,它将接收连接点处可用的任何数据。但是,对于游戏信息滚动显示器,我们可能希望让访问者了解他或她错过了什么。这就是为什么将 id 设置为每个事件的最佳实践。在下面的示例中,我们正在发送 id 作为得分事件的一部分。

<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/',{withCredentials:false});</code>

其值应对于流是唯一的。在本例中,我们使用的是投篮得分的时间。

id 字段成为此事件对象的 lastEventId 属性。但它还有另一个用途。如果连接关闭,浏览器将在其下一个请求中包含一个 Last-Event-ID 头部。将其视为流的书签。如果存在 Last-Event-ID 头部,您可以调整应用程序的响应,以便仅发送在其之后的事件。

处理事件

如上所述,所有事件默认为消息事件。每个消息事件都有三个属性,由 MessageEvent 接口定义。

event.data
返回作为消息事件一部分发送的数据或消息。
event.origin
返回消息的来源,这通常是一个字符串,包含发送消息的方案(例如:http、https)、主机名和端口。
event.lastEventId
返回接收到的最后一个事件的唯一标识符。
每当触发消息事件时,我们的 onmessage 函数都将被调用。这对于您发送消息事件的应用程序来说效果很好。但是,如果您想发送得分或 startingfive 事件(如我们的示例中所示),其局限性就会变得显而易见。使用 addEventListener 更灵活。在下面的代码中,我们正在使用 addEventListener 处理 startingfive 事件。
<code class="language-javascript">var evtsrc = new EventSource('./url_of/event_stream/');
evtsrc.onopen = function(openevent){
    // 连接打开时执行的操作
}</code>

(后续部分,由于篇幅限制,请分段提问。)

以上是服务器范围事件的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn