Skip to main content

EventSource

简介

EventSource 是服务器推送的一个网络事件接口。一个 EventSource 实例会对 HTTP 服务开启一个持久化的连接,以text/event-stream 格式发送事件,会一直保持开启直到被要求关闭。

一旦连接开启,来自服务端传入的消息会以事件的形式分发至你代码中。如果接收消息中有一个事件字段,触发的事件与事件字段的值相同。如果没有事件字段存在,则将触发通用事件。

与 WebSockets,不同的是,服务端推送是单向的。数据信息被单向从服务端到客户端分发。当不需要以消息形式将数据从客户端发送到服务器时,这使它们成为绝佳的选择。例如,对于处理社交媒体状态更新,新闻提要或将数据传递到客户端存储机制(如 IndexedDB 或 Web 存储)之类的,EventSource 无疑是一个有效方案。

https://developer.mozilla.org/zh-CN/docs/Web/API/EventSource

客户端代码示例

  // 创建EventSource实例
  const eventSource = new EventSource('http://tt.xiximiao.top/api/chat/chatStream');
  // 接收服务端消息事件
  eventSource.addEventListener('message', (event) => {
    const message = event.data;
    messagesDiv.innerHTML += `<p>${message}</p>`;
  })
  // 结束会话,关闭链接
  eventSource.addEventListener('close', (event) => {
    eventSource.close()
  })
  // 开启链接事件
  eventSource.addEventListener('open', () => {
    console.log("EventSource: open")
  })
  // 发生错误
  eventSource.addEventListener('error', () => {
    console.log("EventSource: error")
  })

服务端代码示例

    public function chatStream()
{
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

for ($i = 0; $i < 10; $i++) {
echo "id: " . time() . "\n";
echo "data: " . "MSG" . time() . "\n\n";
ob_flush();
flush();
usleep(500000);
}

echo "id: " . time() . "\n";
echo "event: close\n";
echo "data: end\n\n";
ob_flush();
flush();
exit;
}

Nginx增加配置

proxy_buffering off;
gzip off;
fastcgi_keep_conn on;

协议规则

当使用EventSource建立客户端与服务器之间的连接时,客户端将发送一个HTTP GET请求到服务器,请求中包含一个URI用于返回数据流。服务器根据URI返回数据流,数据流中包含一些事件数据,示例如下:

data: This is a message sent at: 2022-01-01 12:00:00\n\n

在上面的示例中,数据流中只有一个“data”字段,表示一条消息。消息内容是一个文本字符串,其中包含了消息的发送时间和一些文本信息。消息以两个“\n”分隔,表示一次消息的结束。

同时,服务器也可以发送事件名称和事件编号等字段,示例如下:

id:1234
event:my_event
data:This is a message sent at: 2022-01-01 12:00:00\n\n

在上面的示例中,数据流中包含了三个字段,分别是事件编号“id”,事件名称“event”和事件数据“data”。客户端可以根据这些字段来处理不同的事件。

另外,当客户端接收到错误信息时,也可以根据具体的错误类型进行相应的处理。比如,如果服务器在返回的数据流中包含了“Retry”字段,则客户端需要等待一段时间后重新建立连接。示例如下:

retry:5000\n\n

在上面的示例中,“Retry”字段表示客户端需要等待5秒后重新建立连接。

EventSource还提供了一些额外的事件和方法用于处理连接状态、错误、超时和解析等方面的问题。其中,最常用的事件是“message”事件,它表示客户端接收到了一条消息。客户端可以通过注册“message”事件来处理收到的数据。示例如下:

const es = new EventSource('/my/events');
es.addEventListener('message', (event) => {
console.log('Received message: ' + event.data);
});

在上面的示例中,我们使用“addEventListener”方法注册了一个“message”事件处理器,当客户端收到一条事件数据时,就会调用这个处理器将事件数据打印出来。

总之,EventSource 提供了一种基于HTTP协议的可靠数据传输方式,用于实时地向客户端推送事件数据。它的使用简单、灵活、可靠,可以广泛应用于诸如消息通知、实时更新等领域。