HTML5 SSE 服务器发送事件

前言

  • HTML5 服务器发送事件(Server-Sent Event)允许网页获得来自服务器的更新。

1、Server-Sent Event

  • Server-Sent 事件指的是网页自动获取来自服务器的更新,单向消息传递。

  • 以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过服务器发送事件,更新能够自动到达。

    • 例如:Facebook/Twitter 更新、股价更新、新的博文、赛事结果等。
  • 在使用 Server-Sent 事件之前,需检测用户的浏览器是否支持它。

    1
    2
    3
    4
    5
    6
    7
    8
    <script>
    if (typeof (EventSource) !== "undefined") {
    // 是的! Server-Sent 支持!
    // 一些代码.....
    } else {
    // 抱歉! Server-Sent 不支持
    }
    </script>

2、创建 Server-Sent 事件

2.1 接收 Server-Sent 事件通知

  • EventSource 对象用于接收服务器发送事件通知,在接收页面所在的 HTML 文件中创建它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <script>
    // 创建 EventSource
    var source = new EventSource("demo_sse.php");

    // 添加 message 事件监听器
    source.onmessage = function (event) {
    document.getElementById("result").innerHTML = event.data;
    };
    </script>
  • 解析

    • 创建一个新的 EventSource 对象,然后规定发送更新的页面的 URL(本例中是 “demo_sse.php”)。
    • 每接收到一次更新,就会发生 onmessage 事件。
    • 当 onmessage 事件发生时,把已接收的数据推入 id 为 “result” 的元素中。
  • 在上面的例子中,使用的 onmessage 事件来获取消息,不过还可以使用其他事件。

事件 描述
onopen 当通往服务器的连接被打开
onmessage 当接收到消息
onerror 当发生错误

2.2 发送 Server-Sent 事件

  • 为了让上面的例子可以运行,还需要能够发送数据更新的服务器(比如 PHP 和 ASP)。

  • 把 “Content-Type” 报头设置为 “text/event-stream”,就可以开始发送事件流了。

  • PHP 代码,demo_sse.php 文件

    1
    2
    3
    4
    5
    6
    7
    8
    <?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');

    $time = date('r');
    echo "data: The server time is: {$time}\n\n";
    flush();
    ?>
  • ASP 代码,demo_sse.asp 文件

    1
    2
    3
    4
    5
    6
    <%
    Response.ContentType="text/event-stream"
    Response.Expires=-1
    Response.Write("data: " & now() & "\n\n")
    Response.Flush()
    %>
  • ASP.NET C# 代码,demo_sse.aspx 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <%@ Page Language="C#"   %>

    <script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
    Response.ContentType = "text/event-stream";
    Response.Expires = -1;
    Response.Write("data:" + DateTime.Now + "\n\n");
    Response.Flush();
    }
    </script>
  • 代码解释:

    • 把报头 “Content-Type” 设置为 “text/event-stream”。
    • 规定不对页面进行缓存。
    • 输出发送日期(始终以 “data: “ 开头)。
    • 向网页刷新输出数据。

2.3 完整的 Server-Sent 事件实例代码

  • demo_sse.php 文件

    1
    2
    3
    4
    5
    6
    7
    8
    <?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');

    $time = date('r');
    echo "data: The server time is: {$time}\n\n";
    flush();
    ?>
  • index.html 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html>

    <html>

    <head>
    <meta charset="utf-8" content="text/event-stream" />
    <title>Qian Chia 工作室</title>
    </head>

    <body>
    <h1>获取服务端更新数据</h1>
    <div id="result"></div>

    <script>
    if (typeof (EventSource) !== "undefined") {

    var source = new EventSource("demo_sse.php");
    source.onmessage = function (event) {
    document.getElementById("result").innerHTML += event.data + "<br />";
    };
    } else {
    document.getElementById("result").innerHTML = "抱歉,你的浏览器不支持 server-sent 事件...";
    }
    </script>
    </body>

    </html>
  • 效果

  • 注意:在浏览器中运行 Server-Sent 事件时,出现以下错误提示:

    1
    EventSource's response has a MIME type ("application/x-httpd-php") that is not "text/event-stream".
    • 原因可能是 PHP 文件没有运行导致,检查运行 demo_sse.php 文件。
    • 或者是 PHP 首先发送默认的 mime 类型头,检查你的 PHP 脚本文件中是否有一些空白(或者一个不可见的字符,比如 utf8-bom) <?php。

3、浏览器支持

元素
服务器发送事件 支持 不支持 支持 支持 支持
文章目录
  1. 1. 前言
  2. 2. 1、Server-Sent Event
  3. 3. 2、创建 Server-Sent 事件
    1. 3.1. 2.1 接收 Server-Sent 事件通知
    2. 3.2. 2.2 发送 Server-Sent 事件
    3. 3.3. 2.3 完整的 Server-Sent 事件实例代码
  4. 4. 3、浏览器支持
隐藏目录