服务器发送的事件:如何以跨浏览器方式自动重新连接?

时间:2015-08-18 18:04:12

标签: javascript php firefox server-sent-events

我实现了一些代码来查询数据库中的任何更改并发送事件。 这是我的PHP脚本的代码

header("Content-Type: text/event-stream");
header('Cache-Control: no-cache');

//****Some code here to query the database

echo "event: message\n";
echo "data: change_from_database \n";
echo "\n\n";
ob_flush();
flush();

我依靠浏览器在每次连接关闭时自动重新连接,因此我不会在我的服务器代码上实现任何循环。此外,我从this thread了解到,实现无限循环有许多缺点。

所以一切正常客户端:每次连接关闭时浏览器都会重新连接,每次服务器发送一个事件时都会触发事件;除了没有重新连接的Firefox(40.0.2)之外。我知道它并不是因为我写了一些JavaScript错误检查代码来测试它:

var evtSource = new EventSource("../sse.php");
evtSource.onerror = function(event){
    var txt;
    switch( event.target.readyState ){
    case EventSource.CONNECTING:
        txt = 'Reconnecting...';
        break;
    }
    console.log(txt);
}

因此,像每一秒一样,chrome上的控制台例如记录"Reconnecting"。另一方面,Firefox重新连接一次,再也不会重新连接。

如何编写代码以使其在Firefox上运行,也许还有其他支持服务器发送事件但不会自动重新连接的浏览器?

3 个答案:

答案 0 :(得分:2)

您可以使用像https://github.com/Yaffle/EventSource这样的polyfill,它应该将事件源功能添加到不支持的浏览器中。

答案 1 :(得分:2)

使用最新版本的Firefox浏览器(44.0.2),您的代码可以完美运行。但是,您可以在错误处理程序中重新初始化EventSource对象,如下所示:

var evtSource = new EventSource("../sse.php");
var evtSourceErrorHandler = function(event){
    var txt;
    switch( event.target.readyState ){
        case EventSource.CONNECTING:
            txt = 'Reconnecting...';
            break;
        case EventSource.CLOSED:
            txt = 'Reinitializing...';
            evtSource = new EventSource("../sse.php");
            evtSource.onerror = evtSourceErrorHandler;
            break;
    }
    console.log(txt);
}

但我强烈建议你不要这样做,因为你的代码没有使用保持连接活动的好处(正如你所写,你知道无限循环)所以浏览器做简单的轮询(你可以在那时看到这一点)网络标签)。我没有看到任何理由在没有保持永久连接的情况下使用SSE而不是AJAX,这显然很难用PHP维护。所以我假设在这种情况下使用简单的AJAX轮询。

答案 2 :(得分:1)

在我的网站上使用您的代码进行测试,一切都按预期使用Firefox 44.0.2和php 5.5。我确实在Mozilla开发网络上遇到了一些有趣的事情,尽管这表明你无法告诉Firefox上的错误信息是什么。也许你的错误检查中的switch语句会让你失望。这是article的链接。查看错误处理部分。

我的php代码与你的相同。万一我做了不同的事情,这里是我的HTML代码。

<!DOCTYPE>
<html>
<head>
    <title>SSE Test</title>
    <meta charset="utf-8" />
    <script>
      var evtSource = new EventSource("sse.php");
      evtSource.onerror = function(event){
        var txt;
        switch( event.target.readyState ){
           case EventSource.CONNECTING:
               txt = 'Reconnecting...';
               break;
        }
        console.log(txt);
      };
    </script>
  </head>
  <body></body>
</html>