繁体   English   中英

根据发送时间使用 AJAX 脚本检索聊天消息

[英]Retrieving chat messages with AJAX script based on time they were sent

我正在为我的任务构建一个带有房间的实时聊天应用程序。 到目前为止一切都很顺利,但我无法从数据库中正确检索最新的聊天消息。 消息表具有以下字段:

| 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 脚本中使用它。 不幸的是,我不太明白如何实现它。

非常感谢任何帮助,谢谢。

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

$.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步:-)

鉴于这个想法不是为了在给定时间之后获取所有消息以至于从上一批消息中获取所有消息,我认为根据消息表的主键而不是时间戳字段。 创建一个客户端变量以记录到目前为止最高(已知)的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

在ajax成功处理程序中,然后使用新批处理中最后一条记录的id更新highestMessageId

当然,这假设您的表使用标准数字键,其中稍后添加的记录具有比先前添加的记录更高的键...

编辑:现在我认为它完全相同的程序也适用于时间戳字段。 当我开始编写上述内容时,我认为时间戳不起作用有一些原因,但我认为我只是在担心一个非问题(我在考虑ajax请求的时间而不是时间戳)记录)。

将上次检索到的时间戳保存在localstorage

<script>
var last_timestamp=localStorage.getItem('last_timestamp')||1;
$.post("/ajax/getmessages.php", {roomID: roomID, timestamp: last_timestamp}, function(resp) {
        resp = $.parseJSON(resp);
   //save last retrieved id 
localStorage.setItem('last_timestamp', resp.new_timestamp);
.....
</script>

当然,浏览器必须支持 localStorage 才能工作。

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

我建议你不要使用时间戳,而是使用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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM