我使用php在我的网站上实现了长轮询。一切都很好,但有一个问题。当我由一个用户打开多个页面时,我无法识别应该在该页面上运行什么事件。若我在一个页面上阻止事件,那个么该事件在另一个页面上将不起作用。如果我不阻止,他们会在每一页上无限地工作。若我检查页面上已工作的事件,它们在刷新页面后仍然可以工作。我错过了正确的解决方案,你能帮我吗?
代码不是很好,但工作
我只需要知道如何做这个
function loadEventAll($uid=0){
if (isset($_POST['event_log'])){
$event_log = json_decode($_POST['event_log']); //here event already worked on page
}
else $event_log = array();
for($i=0;$i<25;$i++){
$now = time();
$time = $now;//-$this->triggered_timeout;
//sql to cut already worked event
$noid = array();
foreach($event_log as $eve){
if(isset($eve->id)) $noid[] = 'id<>'.$eve->id;
}
if (count($noid)) $noid = ' AND ('.implode(' AND ', $noid).') ';
else $noid = '';
//don't try to understand this :)
$q="SELECT * FROM ig_event WHERE (user_id='$uid' OR user_id=0) AND (((triggered+2>=$time OR triggered=0) AND infinite=0) OR (infinite=1 AND triggered+10<=$time)) AND ($now<time_end or infinite=1) AND time_start<=$time $noid";
$link = mysql_query($q);
$arr = array();
if(!$link){
sleep(1);
continue; // if no event occurring start next iteration
}
if (mysql_num_rows($link)){
while ($ddd = mysql_fetch_assoc($link)){
$id = $ddd['id'];
if ($ddd['direct_call']!=""){ //call js function on page
$arr[] = $ddd['direct_call'].':'.$id.':'.$ddd['param'];
if ($ddd['success']!=1){
if (!$ddd['infinite']) $succ = ' success=1';else $succ='';
$ctime = time();
$q = "UPDATE ig_event SET $succ,triggered='$ctime' WHERE id='$id'";
mysql_query($q);
}
}
else{ // usually not used
if ($this->load->module($ddd['module'])){
if (method_exists($this->$ddd['module'], $ddd['action'])){
$time = time();
if (($tarr = $this->$ddd['module']->$ddd['action']($ddd['param'])) and !$ddd['infinite']){
$q = "UPDATE ig_event SET success=1 WHERE id='$id'";
mysql_query($q);
}
}
else{
$q = "UPDATE ig_event SET success=1 WHERE id='$id'";
mysql_query($q);
}
$q = "UPDATE ig_event SET triggered='$time' WHERE id='$id'";
mysql_query($q);
if (!$ddd['infinite']) $arr[] = 'blank'.':'.$id.':';
}
}
}
return $arr;
}
sleep(1);
}
return $arr;
}
下面是我们在实时系统中使用的一个想法。当事件发生时,添加时间戳。例如
id | col1 | col2 | timestamp
------------------------------
1 | herp | derp | 1347373151
2 | herp | derp | 1347373152
3 | herp | derp | 1347373153
现在,当我们开始长轮询时,我们会发送我们捕获的最后一个事件的时间,或者如果是第一个请求,则发送当前时间。然后我们构建查询:
$q = "SELECT * FROM `table` WHERE `timestamp` < ".$lastCaughtEventTime;
如果得到任何结果,请返回它们并退出php脚本。js端应该在从结果集中得到具有最高时间戳的答案后立即重复请求。这样,您的查询将是最小和快速的。示例代码:
function poll() {
$results = [];
$start = microtime(true);
$q = "SELECT * FROM `table` WHERE `timestamp` < " . (int) $_POST['timestamp'];
while (true) {
$result = mysql_query($q);
if (mysql_num_rows($result) > 0) {
$result = returnResults($result);
break;
}
else {
if (time() - $start > POLLING_TIMEOUT) {
die('timeout');
}
sleep(2);
}
}
echo json_encode($result);
}