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

Server-sent events: How do you automatically reconnect in a cross-browser way?

本文关键字:浏览器 方式自 重新连接 事件 服务器      更新时间:2023-09-26

我实现了一些代码来查询数据库中的任何更改并发送事件。这是我的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();

我依靠浏览器在每次连接关闭时自动重新连接,所以我没有在服务器代码上实现任何循环。此外,我从这个线程中了解到实现无限循环有很多缺点。

所以客户端一切都工作得很好:每次连接关闭时浏览器都会重新连接,每次服务器发送一个事件时都会触发一个事件;除了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,也许其他浏览器支持服务器发送的事件,但不自动重新连接?

使用最新版本的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轮询。

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

用你的代码在我的网站上运行测试,一切都如预期的Firefox 44.0.2和php 5.5工作。我在Mozilla开发者网络上发现了一些有趣的事情,你不一定能分辨出v22以后的Firefox的错误信息是什么。也许是错误检查中的开关语句让你失望了。这是文章的链接。查看错误处理部分。

我的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>