javascript - 在 HTML5 服务器发送事件中设置时间间隔

标签 javascript php html server-sent-events

我想从服务器向客户端发送定期更新。为此,我使用了服务器发送的事件。我正在粘贴以下代码:

客户端

获取服务器更新

<script>
if(typeof(EventSource)!="undefined")
{
   var source=new EventSource("demo_see.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>

服务器端

<?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    $x=rand(0,1000);
    echo "data:{$x}\n\n";
    flush();
?>

该代码工作正常,但它每 3 秒 发送一次更新。我想以毫秒为单位发送更新。我在 flush() 之后尝试了 sleep(1) 但它只会将间隔进一步增加 1 秒。有谁知道我如何才能做到这一点?

另外,我可以使用服务器发送的事件发送图像吗?

最佳答案

正如上面评论中所讨论的那样,使用 sleepusleep 在无限循环中运行 PHP 脚本是不正确的,原因有两个

  • 当该脚本仍在运行时,浏览器将看不到任何事件数据(大概它会等待连接先关闭)。我记得 SSE 的早期浏览器实现允许这样做,但现在不再如此。
  • 即使它确实在浏览器端工作,您仍然会面临 PHP 脚本运行时间过长的问题(直到 PHP.ini time_out 设置生效)。如果这种情况发生一两次就可以了。如果有 X 千个浏览器同时从您的服务器寻找相同的 SSE,这将导致您的服务器崩溃。

正确的做法是让您的 PHP 脚本以事件流数据响应,然后像往常一样优雅地终止。如果您想控制浏览器重试的时间,请提供一个 retry 值(以毫秒为单位)。这是一些示例代码

function yourEventData(&$retry)
{
 //do your own stuff here and return your event data.
 //You might want to return a $retry value (milliseconds)
 //so the browser knows when to try again (not the default 3000 ms)
}

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Origin: *');//optional

$data = yourEventData($retry);

echo "data:{$str}\n\nretry:{$retry}\n\n";

作为对原始问题的回答,这有点但为了完整起见:

用这种方式轮询服务器得到的只是数据。之后你用它做什么完全取决于你。如果您想将这些数据视为图像并更新网页中显示的图像,您只需执行以下操作

document.getElementById("imageID").src = "data:image/png;base64," + Your event stream data;

关于这些原则。我有时忘记了 retry 必须以毫秒为单位并最终返回,例如 retry:5\n\n 令我惊讶的是,它仍然有效.但是,我会犹豫使用 SSE 以 100 毫秒的间隔更新浏览器端图像。更典型的用法是按照以下几行

  • 用户在服务器上请求作业。该作业要么排队在其他作业之后,要么可能需要相当多的时间来执行(例如创建 PDF 或 Excel 电子表格并将其发回)
  • 与其让用户在没有反馈的情况下等待 - 并冒着超时的风险 - 不如启动一个 SSE,告诉浏览器作业完成的预计到达时间,并设置一个 retry 值,这样浏览器知道何时再次查找结果。
  • ETA 用于向用户提供一些反馈
  • 在 ETA 结束时,浏览器将再次查看(浏览器会自动执行此操作,因此您无需执行任何操作)
  • 如果由于某种原因作业没有被服务器完成,它应该在事件流中指出它返回,例如data{"code":-1}\n\n 以便浏览器端代码可以优雅地处理这种情况。

还有其他使用场景 - 更新股票报价、新闻标题等。以 100 毫秒的间隔更新图像感觉 - 纯粹个人观点 - 就像滥用技术。


自从我发布这个答案到现在已经快 5 年了,它仍然经常被点赞。为了任何仍在使用它作为引用的人的利益——在我看来,在许多方面,SSE 是一种相当过时的技术。随着对 WebSockets 的广泛支持的出现,为什么还要费心做 SSE。除了其他任何事情之外,为每次浏览器端重试从浏览器设置和断开 HTTPS 连接的成本非常高。 WSS 协议(protocol)的效率要高得多。

如果你想实现 websockets 的阅读点

  1. Client Side
  2. Server side via PHP with Ratchet
  3. With Nginx and NChan

在我看来,PHP 不是一种处理 websockets 的好语言,而且 Ratchet 远非易于设置。 Nginx/NChan 路线要容易得多。

关于javascript - 在 HTML5 服务器发送事件中设置时间间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16315137/

相关文章:

php - 使用 PHP/MySQL 实现购物车的最佳方式

javascript - jquery 插入数据到下一行

javascript - 试图理解递归函数的类似堆栈的行为

javascript - 重新加载后相同的功能没有给出相同的结果

javascript - 旧 jsp 文件中 &lt;!-- code here//--> block 的必要性

javascript - 检查数组中是否有重复项

PHP 日期在减去一个月时返回错误的月份

php - 将重命名的文件名上传到数据库

html - 如何让 Internet Explorer 正确显示此图像

html - Bootstrap 设置列高和间距