2012-01-10 55 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 

在客户端得到结果后,请不要拖延,立即发出下一个请求。