为什么服务器发送的事件每3秒启动一次?

时间:2018-12-21 16:29:00

标签: javascript php server-sent-events

我是服务器发送事件的新手,因此我正在WAMP Server上尝试this W3Schools example。我拥有的文件是:

demo_sse.php

<?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.php

<!DOCTYPE html>
<html>
  <body>
    <h1>Getting server updates</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 = "Sorry, your browser does not support server-sent events...";
      }
    </script>
  </body>
</html>

据我了解,时间在不断变化,因此更新必须至少每秒发送一次。但是,每三秒钟接收一次更新。在demo_sse.php中未指定此间隔,因此:

  • 为什么每3秒发送一次更新?
  • 如何更改此间隔?

2 个答案:

答案 0 :(得分:2)

W3Schools上的示例有点不好。

对于大多数HTTP响应/请求交换,客户端向服务器发出HTTP请求,服务器发送回数据并且交换完成。

对于SSE(尽管它仍然使用HTTP协议),这有点不同。客户端在这里向服务器发出请求,会话保持打开状态,服务器可以在需要时发送数据。如果由于某种原因关闭了会话,则EventSource将尝试重新连接,然后一切重新开始。

PHP脚本中的问题是该脚本在完成最后一行之后结束了请求/响应交换。这意味着连接已关闭,因此EventSource将尝试重新连接。 (添加.onerror事件将显示在每条消息之后引发错误。)

the specification中所定义:

  

重新连接时间,以毫秒为单位。最初,该值必须是用户代理定义的值,可能在几秒钟的范围内。

这就是为什么您每三秒钟收到一次更新。因为这就是用户代理定义的值。

在该行下方,您还可以看到:

  

除url以外,当前未在EventSource对象上公开。

这意味着当前无法通过JavaScript设置此值。

尽管可以通过在SSE消息的retry字段中定义它来从服务器上设置此值。您可以在此处以毫秒为单位定义用户代理在重新连接到服务器之前应等待多长时间。如果要将其设置为一秒,则应为:

$time = date('r');
// If the connection closes, retry in 1 second
echo "retry: 1000\n";
echo "data: The server time is: {$time}\n\n";
flush();

但是当然最好在没有第一个消息后关闭连接的情况下正确实现SSE。

A good explanation can be found on MDN。我建议通常在W3Schools上使用MDN。 W3Schools is not the most liked resource here on Stack Overflow,这是一个很好的例子。

答案 1 :(得分:1)

根据this article,最近HTML5 Rocks

  

神奇的部分是,每当连接关闭时,   3秒钟后,浏览器将自动重新连接到源。   您的服务器实施甚至可以对此进行控制   重新连接超时。参见Controlling the reconnection-timeout   下一节。

demo_sse.phpflush之后结束,因此连接被关闭;浏览器将在3(ish)秒内自动重新连接。

要控制服务器上的重新连接超时,可以在流中发送一个retry字段。从this MDN doc中可以确定,如果您添加 echo "retry: 1000\n\n";行之前的echo "data:行,它将超时更改为1秒。