2012-01-10 51 views
0

我正在爲我的任務構建一個帶有聊天室的實時聊天應用程序。到目前爲止,一切都很順利,但我無法正確地從數據庫中檢索最新的聊天消息。消息表具有以下字段:基於AJAX腳本基於發送時間檢索聊天消息

| m_id | u_id | r_id | message | sent |

m_id是主鍵。 u_idr_id是其他表的外鍵,用於引用發送消息的用戶以及他們發送消息的房間。該sent場在PHP的microtime(true)格式有數據:

1326174129.977 

我已經建立了我的AJAX腳本,從數據庫中檢索信息,它看起來像這樣:

function getMessages() { 
    var d = new Date(); 
    $.post("/ajax/getmessages.php", {roomID: roomID, timestamp: timestamp}, function(resp) { 
     resp = $.parseJSON(resp); 

     for(x in resp) { 
      $('#chat-holder ul').append('<li>[' + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + '] <strong>' + resp[x].u_id + '</strong>: ' + resp[x].msg + '</li>'); 
      $("#chat-holder").scrollTop($("#chat-holder")[0].scrollHeight); 
     } 
    }); 
} 

getMessages函數運行一次,第二,然後當它從getmessages.php腳本中回收數據時,它將通過JSON編碼的響應和廣告列表項循環訪問聊天框。很簡單。

問題是,它將檢索發送到房間的所有消息,而不僅僅是自上次用戶輪詢最新消息後發送的消息。所以我最終會在聊天中發送的每條消息每秒都被添加到聊天框中。

我唯一想出的就是存儲上次用戶請求消息的時間戳,然後以某種方式在後端PHP腳本中使用它。不幸的是,我無法理解如何實現它。

任何幫助非常感謝,謝謝。

回答

1

鑑於這個想法並不是爲了在給定時間後獲取所有消息,以至於從上一批消息後獲取所有消息,我認爲根據消息表的內容做到這一點會更容易主鍵而不是時間戳字段。創建一個客戶端的變量要注意最高(已知)ID至今:

var highestMessageId = 0; 

然後,當你讓你的Ajax請求傳遞ID通過對PHP:

$.post("/ajax/getmessages.php", {roomID: roomID, fromMessageId : highestMessageId}, 

然後在你的PHP :

SELECT * FROM messages 
WHERE r_id = $r_id 
AND m_id > $m_id 

在阿賈克斯成功處理程序,那麼你更新highestMessageId與新批次中的最後記錄的ID。

當然,這假設你的表使用其中的記錄後加入比剛纔添加的記錄高鍵標準的數字鍵...

編輯:現在,我想它完全一樣的程序將與合作時間戳字段也是如此。當我開始寫上述內容時,我認爲時間戳不起作用是有原因的,但我認爲我只是在困惑自己擔心一個非問題(我在考慮ajax請求的時間而不是時間戳)記錄)。

1

是的,你的想法是正確的。

$.post("/ajax/getmessages.php", {roomID: roomID, timestamp: timestamp}, 

該時間戳來自哪裏?

無論如何,在服務器上,你應該這樣做(僞代碼):

SELECT * 
FROM messages 
WHERE r_id = $roomID AND sent > $timestamp 
ORDER BY sent; 

然後你發出這些數據的客戶端,與最新的時間戳(最後一排的sent值)一起。

{timestamp: $last_sent, 
messages: [...] 
} 

然後,在你的AJAX回調你這樣做:

resp = $.parseJSON(resp); 

last_timestamp = resp['timestamp']; 

for(x in resp['messages']) { 
    // ... 
} 

然後你在下次請求使用last_timestamp

$.post("/ajax/getmessages.php", {roomID: roomID, timestamp: last_timestamp}, ... 

轉到第1步:-)

0

添加WHERE created > DATE_SUB(date(NOW()), INTERVAL 1 hour) ORDER BY created子句您的SQL,例如。

0

我建議您不要使用時間戳,而是用於下載最新消息的ID。當數據庫中有成千上萬條消息時,這會帶來更好的性能。

而且,我不會每秒鐘下載消息,而是會在服務器上延遲它,這意味着服務器在至少有一條新消息到達之前不會給出響應。像這樣:

$start = time(); 
$query = mysql_query(...); 
while(mysql_num_rows($query)==0 && time()-$start < 25) { 
    usleep(200000); // we wait for 200 ms so the server won't be overloaded 
    $query = mysql_query(...); 
} 
//print out the results 

在客戶端得到結果後,請不要拖延,立即發出下一個請求。