我正在使用SSE事件将用户的朋友请求数从服务器推送到客户端。但是当我这样做时,网站的其他页面会卡住并继续加载(可能是由于用户会话锁定)。如何将SSE事件数据推送到客户端,而不是在会话运行时让其他页面等待?
我在客户端有一个事件监听器,如下所示:
var evtSource = new EventSource("friend-req.php");
var eventList = $('#list'); //this is div's ID on xhtml page
$(document).ready(function(){
$(function(){
evtSource.addEventListener("requests", function(e) {
var newElement = document.createElement("li");
var obj = JSON.parse(e.data);
newElement.innerHTML = "friend request count: " + obj.count;
eventList.append(newElement);
}, false);
});
});

在服务器端,我使用while循环事件(如SO上的大量文章所示)。首先,我从数据库中获取当前会话用户的朋友请求计数,然后针对事件请求' (客户正在收听)。
<?php
//friend-req.php file
session_start();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
include_once 'db.php';
$db = new db();
while (1) {
$user = $_SESSION['user'];
$q = "select count(*) num from requests where status = 1 and id = $user";
$result = $db->select($q) or die("Query Failed:" . $db->last_error);
if($result)
{
$r = $db->get_row($result);
echo "event: requests\n";
echo 'data: {"count": "' . $r['num'] . '"}';
echo "\n\n";
}
ob_flush();
flush();
sleep(5);
}
?>
问题是,当我运行客户端脚本时,它运行正常,但我的其他页面都没有加载。我已经搜索了解决方案,但是在SO和其他网站上都没有找到任何满意的答案。告诉我如何通过会话发送服务器端事件,而不是让其他页面等待(或者如果方法中存在任何缺陷/更好的方法)
答案 0 :(得分:1)
我认为问题出现在“session_start()
”中:每个会话锁定服务器中的文件,因此没有其他脚本可以开始使用相同的会话(它们都挂在“session_start()
”调用上)直到第一个脚本结束和/或释放锁定。您的脚本应该读取循环外的$ user,然后调用session_commit()
,以便其他脚本可以运行。请记住,会话锁定始终会阻止脚本的并行执行:如果您已完成读取或修改会话变量,请始终在脚本中调用session_commit()
,以便其他脚本可以在第一个完成其详细说明时运行(google around for other more精心解决方案)。这非常重要,例如,如果您的浏览器使用会话对您的php
代码执行了大量异步ajax调用:没有“session_commit()
”您将看到您的服务器响应请求没有任何平行的时间