这是我的 sse_server.php 文件
include_once 'server_files/init2.php'; //this file includes the connection file to the database and some functions
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$assocArray = array();
$fetch_article = $dbh->prepare("SELECT
article_author_id,
article_author_un,
article_id,
article_cover,
article_title,
article_desc
FROM articles ORDER BY article_id DESC");
$fetch_article->execute();
while ($fetch = $fetch_article->fetch(PDO::FETCH_ASSOC))
{
$article_author_id = $fetch['article_author_id'];
$article_author_u = $fetch['article_author_un'];
$article_id = $fetch['article_id'];
$article_cover = $fetch['article_cover'];
$article_title = $fetch['article_title'];
$article_desc = $fetch['article_desc'];
$randomNum = rand(0,500);
//Insert the Random Number along with the article's info | Random Number as a Value and the contents as a Key
$assocArray[
'randomNum'.'|'. //0
$article_author_id.'|'. //1
$article_author_u.'|'. //2
$article_id.'|'. //3
$article_cover.'|'. //4
$article_title.'|'. //5
$article_desc //6
] = $randomNum;
}
//sort the array
arsort($assocArray, 1);
//echo '<pre>';
//print_r($assocArray);
//while(true){
$var = '';
foreach ($assocArray as $key => $value) {
$var .= $value .' => ' . $key . '`|||`<br>';
}
echo "retry: 6000\n";
echo "data: {$var}\n\n";
ob_flush();
flush();
//}
这就是我在 client.php 文件中处理数据的方式
<div id="feeds"></div>
<script>
if(typeof(EventSource)!=="undefined") {
var eSource = new EventSource("sse_server.php");
//detect message received
eSource.addEventListener('message', function(event) {
var jsV_feeds = event.data;
var eventList = document.getElementById("feeds");
var jsV_feedsArray = jsV_feeds.split('`|||`'); //Seperator
eventList.innerHTML = jsF_ToFetch(jsV_feedsArray);
}, false);
}
else {
document.getElementById("feeds").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
}
function jsF_ToFetch(jsP_array)
{
var string = ''; //an empty string
for (var i = 0; i < jsP_array.length-1; i++)
{
jsV_Feed = jsP_array[i].split('|');
jsV_randomNum = jsV_Feed[0];
jsV_article_author_id = jsV_Feed[1];
jsV_article_author_u = jsV_Feed[2];
jsV_article_id = jsV_Feed[3];
jsV_article_cover = jsV_Feed[4];
jsV_article_title = jsV_Feed[5];
jsV_article_desc = jsV_Feed[6];
string += jsV_randomNum +'<li><b>'+jsV_article_author_u+'</b><!--process the rest in a similar way--> </li>';
} // for loop ENDS here
return '<ol>' + string + '</ol>';
}
</script>
问题是如果我只使用foreach
循环,它会每6秒重新连接一次
如果我将foreach
包裹在while
循环中,它会使连接保持活动状态,但继续发送数据。这最终会在几秒钟内加载大量数据。此外,它使AJAX Post请求非常慢,同时通过另一个页面执行。
为什么会这样?
如何让它保持连接打开,不发送数据,也不会减慢AJAX帖子请求的速度。
PS:我访问了这些链接 -
http://www.html5rocks.com/en/tutorials/eventsource/basics/
PHP Event Source keeps executing
可能是我对他们的了解不够。如果它可以归结为更简单的术语,请善待它!
提前致谢!
答案 0 :(得分:1)
您希望使用已在sse_server.php中注释掉的while(true){}
循环。您的SSE脚本永远不会退出(直到套接字关闭,这将发生在客户端,即您的JavaScript脚本关闭它,或者浏览器窗口关闭)。
使用while循环时遇到问题的原因是while循环中没有sleep()
或等待操作。因此,您要以最大速率向客户端发送数据(一遍又一遍地重复相同的数据!)。
从概念上讲,我猜你所追求的是这段代码:
$lastID = 0;
while(true){
$fetch_article = $dbh->prepare("SELECT something FROM somewhere WHERE conditions AND articleID > ?");
$results = $fetch_article->execute($lastID);
if(has 1+ results) {
foreach($results){
echo result formatted for SSE
$lastID = ...;
}
flush();ob_flush();
}
sleep(5);
}
这表示它将每隔5秒轮询数据库以查找新记录。如果没有新的记录它什么都不做 - 只需再回到睡眠状态5秒钟。但如果有新的记录,它会通过SSE将它们推送给客户端。
您可以调整5秒睡眠以找到服务器上CPU使用率与延迟之间的平衡。睡眠时间越短意味着延迟越低(您的客户端越早获得新数据),但服务器上的CPU越高。
旁白:上面的lastID
方法只是检测您所看到的记录的一些方法,但还没有看到。如果您的表中有唯一ID,那就很好AUTO_INCREMENT
。但是,或者,如果插入带有created
时间戳的DB记录,则查询将变为:
$now = 0;
while(true){
$stmt = prepare( "SELECT ... AND created > ?" );
$stmt->execute( $now );
$now = time();
...process results ...
sleep(5);
}
(稍微更安全的是将$now
设置为在结果中找到的最大created
时间戳,而不是每次都设置为time()
;否则记录可能会滑过裂缝,而不是发送给客户。)