2015-04-02 45 views
0

我正在使用SSE事件將用戶的朋友請求數從服務器推送到客戶端。但是當我這樣做時,網站的其他頁面卡住並繼續加載(可能是由於用戶會話鎖定)。如何將SSE事件數據推送到客戶端,並且在會話運行時不讓其他頁面等待?如何使服務器發送事件(SSE)與PHP會話一起工作?

我在客戶端的事件監聽器,如下所示:

var evtSource = new EventSource("friend-req.php"); 
 
var eventList = $('#list'); //this is div's ID on xhtml page 
 
$(document).ready(function(){ 
 
\t 
 
$(function(){ 
 
\t evtSource.addEventListener("requests", function(e) { 
 
\t \t var newElement = document.createElement("li"); 
 
\t \t \t 
 
\t \t var obj = JSON.parse(e.data); 
 
\t \t newElement.innerHTML = "friend request count: " + obj.count; 
 
\t \t eventList.append(newElement); 
 
\t }, false); 
 
}); 
 
});

在服務器端,我使用的是事件,而環(作爲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

你克服了這個問題嗎?你是否讓其他頁面加載? BOS我也面臨着與上海證券交易所同樣的問題。 – Ram 2015-10-20 06:12:37

回答

1

我認爲問題出在「session_start()」:每個會話鎖一個文件在服務器,所以沒有其他腳本可以開始使用相同的會話(它們都掛在他們的「session_start()」調用),直到第一個腳本結束和/或釋放鎖。您的腳本應讀取循環外部的$用戶,然後調用session_commit(),以便其他腳本可以運行。請記住,會話鎖定總是會阻止腳本的並行執行:如果您已完成讀取或修改會話變量,則始終在腳本中調用session_commit(),以便其他腳本可以在第一次完成其詳細說明時運行(有關其他更詳細的解決方案的Google)。例如,如果您的瀏覽器使用會話對您的php代碼執行了大量異步AJAX調用,則非常重要:如果沒有「session_commit()」,您將看到您的服務器在某個時間沒有任何並行性地響應請求

相關問題