【问题标题】:HTML5 Server-Sent EventHTML5 服务器发送事件
【发布时间】:2017-07-21 12:05:07
【问题描述】:

我正在尝试使用 SSE 构建实时应用程序。 但是当我认为我以正确的方式编写所有内容时,它就不起作用了。 请帮我解决这个问题。 我知道 websockets 比 SSE 好,但我刚开始 这是我的 index.html 代码

<!DOCTYPE html>
<html>
<head>
<title>Using SSE(Server-sent event)</title>
<meta charset="utf-8">
</head>
<body>

<h1>Getting server updates</h1>
<div id="result"></div>

<script>
if(typeof(EventSource) !== "undefined") {
    var source = new EventSource("getdata.php");
    source.onmessage = function(event) {  
        console.log(JSON.parse(event.data));
    };
} else {
    document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>

</body>
</html>

这是getdata.php页面

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

    $pdo = new PDO("mysql:host=localhost;dbname=sse", 'root', 'secret');
    $obj = $pdo->query("select * from users");
    $arr = $obj->fetchAll();
    echo "data: ".json_encode($arr);
    flush();
   ?>

当我使用时

source.onerror = function(er){
   console.log(er);   
}

我收到了

error { target: EventSource, isTrusted: true, currentTarget: EventSource, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, composed: false, timeStamp: 5152.813223, cancelBubble: false, originalTarget: EventSource }

我在 html console.log(JSON.parse(event.data)); 中尝试了注释代码 但它也不起作用。

请帮助了解 SSE 的工作原理以及我的代码有什么问题?

提前致谢。

【问题讨论】:

  • 请定义“不起作用”。你得到什么错误?什么意外行为?
  • 我用过source.onrror = function(er){ console.log(er); } 我得到了这个error { target: EventSource, isTrusted: true, currentTarget: EventSource, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, composed: false, timeStamp: 5152.813223, cancelBubble: false, originalTarget: EventSource }
  • 正确。那么请在问题的代码中包含它。 cmets中的代码很难阅读,而且人们可能会错过细节
  • @ADyson 感谢您的关注。我已经更新了我的问题。

标签: javascript php html real-time server-sent-events


【解决方案1】:

我发现它为什么不起作用。 我加了\n\n

echo "data: ".json_encode($arr);

原来是这样的

echo "data: ".json.encode($arr)."\n\n";

希望对你有帮助

【讨论】:

    【解决方案2】:

    编辑(只是为了留给未来的观众)

    check(然后在浏览器中按 F12 并检查“控制台” - 它在 Firefox 和 Chrome 中对我有用)

    查看该服务器上的代码:

    sse.html

    <!DOCTYPE html>
    <html>
    <head>
    <title>Using SSE(Server-sent event)</title>
    <meta charset="utf-8">
    </head>
    <body>
    
    <h1>Getting server updates</h1>
    <div id="result"></div>
    
    <script>
    if(typeof(EventSource) !== "undefined") {
        var source = new EventSource("getdata.php");
        source.onmessage = function(event) {  
            console.log(JSON.parse(event.data));
        };
    } else {
        document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
    }
    </script>
    
    </body>
    </html>
    

    getdata.php(仍然是 mysql,不是 msqli 或 PDO,因为服务器较旧)

    <?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    
    include("../../admin2/config.inc.php");
    connect_db();
    $query = mysql_query( "select * from ttbb" ) or die( mysql_error() );
    $arr = mysql_fetch_object( $query );
    echo "data: ".json_encode($arr)."\n\n";
    flush();
    ?>
    

    打印:

    【讨论】:

    • 我检查了控制台。它不工作并触发错误事件。
    • 检查我的答案,添加了最近的打印
    • 像什么服务器配置可能有问题?这是错误的......当我只使用字符串(而不是 json)时它也可以工作
    【解决方案3】:

    首先,也是最重要的,PHP 脚本应该永远运行,而不是执行一个查询然后死掉。 (如果这是您的意图,那么您不需要流式解决方案,而应该只使用 AJAX。)

    其次,在每个data:: 之后需要两个 LF。除了flush(),你(可能)还需要ob_flush()。有了所有三个更改,它看起来像这样:

    <?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    
    $pdo = new PDO("mysql:host=localhost;dbname=sse", 'root', 'secret');
    while(true){  //Deliberate infinite loop
      $obj = $pdo->query("select * from users");
      $arr = $obj->fetchAll();
      echo "data: ".json_encode($arr)."\n\n";
      @ob_flush();@flush();  //Use @ to suppress v.rare but meaningless errors
      sleep(1);  //Poll the database every second.
      }
    

    ?>

    我已将它(服务器)设置为每秒轮询本地数据库。您应该根据服务器负载与目标延迟之间的平衡进行调整。

    重要提示:这将每秒向所有客户端发送所有用户数据。您应该重新设计您的 SQL 查询以仅获取自上次查询以来已更改的用户。然后重新设计前端以在第一次调用时为所有用户提供,然后再进行更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 2015-09-24
      相关资源
      最近更新 更多