2013-04-01 214 views
12

我正在尋找一個長時間輪詢jQuery和PHP的消息系統。我很想知道實現這一目標的最佳/最有效的方法。我立足於此Simple Long Polling Example長查詢 - 消息系統

如果用戶正坐在收件箱頁面上,我想插入任何新消息。我見過的一個想法是在消息表中添加一個last_checked列。 PHP腳本看起來像這樣:

query to check for all null `last_checked` messages 
if there are any... 
while(...) { 
    add data to array 
    update `last_checked` column to current time 
} 
send data back 

我喜歡這個想法,但我想知道別人怎麼看它。這是解決這個問題的理想方式嗎?任何信息都將有所幫助!

要添加,沒有設定的使用次數可能在網站上,所以我正在尋找一種有效的方式來做到這一點。

+0

這是一個很好的問題,我正要問同樣的問題。 – samayo

回答

8

是的,你描述它的方式是長輪詢方法是如何工作的。 您的示例代碼有點模糊,所以我想補充一點,您應該在while循環內執行sleep()一小段時間,並且每次比較last_checked時間(存儲在服務器端)和current時間(這是從客戶端發送的內容)。

事情是這樣的:

$current = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0; 
$last_checked = getLastCheckedTime(); //returns the last time db accessed 

while($last_checked <= $current) { 
    usleep(100000); 
    $last_checked = getLastCheckedTime(); 
} 

$response = array(); 
$response['latestData'] = getLatestData() //fetches all the data you want based on time 
$response['timestamp'] = $last_checked; 
echo json_encode($response);  

而在您的客戶端JS你有這樣的:

function longPolling(){ 
     $.ajax({ 
      type : 'Get', 
      url : 'data.php?timestamp=' + timestamp, 
      async : true, 
      cache : false, 

      success : function(data) { 
       var jsonData = eval('(' + data + ')'); 
       //do something with the data, eg display them 
       timestamp = jsonData['timestamp']; 
       setTimeout('longPolling()', 1000); 
      }, 
      error : function(XMLHttpRequest, textstatus, error) { 
        alert(error); 
        setTimeout('longPolling()', 15000); 
      }  
     }); 
} 
+0

欣賞答案!函數getLastCheckedTime包含什麼?我知道你說過它返回上次訪問數據庫的時間,但我該如何判斷? db中的列? – SeanWM

+0

另外,我是否應該在if語句中沒有最後四行? – SeanWM

+0

是的'getLastCheckedTime();'必須返回db中列的結果,當插入新消息時它將自動更新。 最後四行不一定要在'if'語句中,因爲只有當新數據被插入到數據庫中時纔會執行,因此只有'while'纔會被中斷。 –

1

如果你只有一個用戶,那很好。如果你不這樣做,你會遇到併發症。通過這樣做,你還可以運行一大堆SELECT查詢。

由於PHP沒有任何跨客戶端事件驅動的可能性,我一直堅信一段時間PHP和長輪詢不會在本地工作。這意味着你需要每秒鐘檢查你的數據庫/ 2s/5s而不是依賴事件。

但是,如果你仍然想這樣做,我會讓你的消息系統在用戶有消息時在目錄中寫一個[nameofuser] .txt文件,然後用這個觸發器檢查消息是否存在。如果文件存在並且不爲空,請啓動請求以獲取消息,處理,反饋並刪除文本文件。這將減少你的SQL開銷,同時(如果你不小心)增加你的磁盤IO。

從結構上看,關聯表是迄今爲止最好的。製作一張專門用於檢查狀態的新表格,列有三列:user_idmessage_idread_at。用法應該很明顯。不在那裏的任何組合都是未讀的。

2

而不是添加新列作爲last_checked您可以添加爲last_checked_time。所以你可以從last_checked_timecurrent_time

(i.e) DATA BETWEEN `last_checked_time` AND `current_time` 
1

而是創建一個名爲last_checked列的,你可以創建一個名爲柱:檢驗。 如果將所有消息保存在數據庫中,則可以更新數據庫中的字段。例如:

  1. 用戶1向用戶2發送消息。
  2. PHP使用長輪詢系統接收消息並將消息保存在表中。
  3. 用戶2在線時會向服務器發送一個信號,通知服務器用戶1已準備好接收消息
  4. 服務器檢查所有未被「檢查」的消息並返回它們。