Javascript 长轮询:为什么有些消息会出现两次?
我目前正在构建一个带有日志轮询的聊天应用程序。 原型位于此处: 在服务器端使用PHP。但我认为这是一个javascript问题,有些消息会出现几次 使用的javascript代码是:Javascript 长轮询:为什么有些消息会出现两次?,javascript,php,ajax,chat,long-polling,Javascript,Php,Ajax,Chat,Long Polling,我目前正在构建一个带有日志轮询的聊天应用程序。 原型位于此处: 在服务器端使用PHP。但我认为这是一个javascript问题,有些消息会出现几次 使用的javascript代码是: var t; var xhr; var ids = []; var panel = $('#posts-panel'); var indexOf = function(needle) { if(typeof Array.prototype.indexOf === 'function') {
var t;
var xhr;
var ids = [];
var panel = $('#posts-panel');
var indexOf = function(needle) {
if(typeof Array.prototype.indexOf === 'function') {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function(needle) {
var i = -1, index = -1;
for(i = 0; i < this.length; i++) {
if(this[i] === needle) {
index = i;
break;
}
}
return index;
};
}
return indexOf.call(this, needle);
};
function getNewPosts(timestamp) {
xhr = $.ajax({
url: 'chat.php',
data: 'timestamp=' + timestamp,
dataType: 'JSON',
})
.done(function(data) {
clearInterval( t );
// If there was results or no results
// In both cases we start another AJAX request for long polling after 1 second
if (data.message_content == 'results' || data.message_content == 'no-results') {
t = setTimeout(function() { getNewPosts(data.timestamp); }, 1000);
// If there was results we will append it to the post div
if (data.message_content == 'results') {
// Loop through each post and output it to the screen
$.each(data.posts, function(index, val) {
if(indexOf.call(ids, val.msg_id) == '-1') {
ids.push(val.msg_id);
$('<li class="media"><div class="media-body"><div class="media"><a class="pull-left" href="#"><img class="media-object img-circle " src="assets/img/user.png" /></a><div class="media-body" >'+val.message_body+'<br /><small class="text-muted">Alex Deo | '+ val.posted_time +'</small><hr /></div></div></div></li>').appendTo('.posts');
panel.scrollTop(panel[0].scrollHeight);
}
});
}
}
});
}
$(document).ready(function(){
$(function() {
$('#posts-panel').jScrollPane({
horizontalGutter:5,
verticalGutter:5,
'showArrows': false
});
});
$('.jspDrag').hide();
$('.jspScrollable').mouseenter(function(){
$(this).find('.jspDrag').stop(true, true).fadeIn('slow');
});
$('.jspScrollable').mouseleave(function(){
$(this).find('.jspDrag').stop(true, true).fadeOut('slow');
});
if (!Date.now) {
Date.now = function() { return new Date().getTime(); };
}
panel.scrollTop(panel[0].scrollHeight);
// Create an AJAX request to the server for the first time to get the posts
$.ajax({
async: false,
url: 'chat.php?full_page_reload=1',
type: 'GET',
dataType: 'JSON',
})
.done(function(data) {
// Assign the this variable to the server timestamp
// that was given by the PHP script
serverTimestamp = data.timestamp;
if(data.posts != 'nothing') {
$.each(data.posts, function(index, val) {
ids.push(val.msg_id);
$('<li class="media"><div class="media-body"><div class="media"><a class="pull-left" href="#"><img class="media-object img-circle " src="assets/img/user.png" /></a><div class="media-body" >'+val.message_body+'<br /><small class="text-muted">Alex Deo | '+ val.posted_time +'</small><hr /></div></div></div></li>').appendTo('.posts');
panel.scrollTop(panel[0].scrollHeight);
});
}
})
.fail(function() {
alert('There was an error!');
});
// When the form is submitted
$('#sendMessage').on('submit', function(event) {
// xhr.abort();
$.ajax({
url: 'chat.php?post=1',
type: 'POST',
dataType: 'JSON',
data: $('#sendMessage').serialize()
})
.done(function(data) {
// Reset the form values
$('#sendMessage')[0].reset();
})
.fail(function() {
// When there was an error
alert('An error occured');
});
// Prevent the default action
event.preventDefault();
});
// Start the actual long polling when DOM is ready
getNewPosts(serverTimestamp);
});
vart;
var-xhr;
var-id=[];
变量面板=$(“#posts面板”);
var indexOf=功能(指针){
if(typeof Array.prototype.indexOf==='function'){
indexOf=Array.prototype.indexOf;
}否则{
indexOf=功能(指针){
变量i=-1,指数=-1;
对于(i=0;i”+val.message_body+”
Alex Deo |“+val.posted_time+”
)。附录(“.posts”);
panel.scrollTop(面板[0].scrollHeight);
}
});
}
}
});
}
$(文档).ready(函数(){
$(函数(){
$(“#帖子面板”).jScrollPane({
水平排水沟:5,
垂直排水沟:5,
“showArrows”:错误
});
});
$('.jspDrag').hide();
$('.jspScrollable').mouseenter(函数(){
$(this.find('.jspDrag').stop(true,true.fadeIn('slow');
});
$('.jspScrollable').mouseleave(函数(){
$(this.find('.jspDrag').stop(true,true.fadeOut('slow');
});
如果(!Date.now){
Date.now=function(){return new Date().getTime();};
}
panel.scrollTop(面板[0].scrollHeight);
//第一次向服务器创建AJAX请求以获取帖子
$.ajax({
async:false,
url:'chat.php?完整页面\重新加载=1',
键入:“GET”,
数据类型:“JSON”,
})
.完成(功能(数据){
//将此变量分配给服务器时间戳
//这是由PHP脚本给出的
serverTimestamp=data.timestamp;
如果(data.posts!='nothing'){
$.each(data.posts,函数(index,val){
id.push(val.msg_id);
$(“”+val.message_body+”
Alex Deo |“+val.posted_time+”
)。附录(“.posts”);
panel.scrollTop(面板[0].scrollHeight);
});
}
})
.fail(函数(){
警报(“发生错误!”);
});
//提交表格时
$('#sendMessage')。在('submit',函数(事件){
//xhr.abort();
$.ajax({
url:'chat.php?post=1',
键入:“POST”,
数据类型:“JSON”,
数据:$('#sendMessage')。序列化()
})
.完成(功能(数据){
//重置表单值
$('#sendMessage')[0].reset();
})
.fail(函数(){
//当发生错误时
警报(“发生错误”);
});
//阻止默认操作
event.preventDefault();
});
//在DOM就绪时启动实际的长轮询
getNewPosts(服务器时间戳);
});
请帮助我解决此问题。确保消息不会出现两次的一种方法是在您已有的循环函数中使用ID检查DOM中是否存在该消息:
$.each(data.posts, function(index, val) {
if(!$('#message-'+val.id).length) {
// Add message to the DOM
}
});
如果消息已在DOM中,则不会再次添加它。我看到您在响应中已经有了一个ID,所以这样做非常简单。顺便说一句:这是正常的轮询,不是@最后面的轮询,不是服务器端的轮询。服务器保持连接打开,直到它通过每秒轮询数据库收到来自数据库的新消息。但它会通过心跳关闭连接,因为它在15秒内没有收到来自数据库的新消息。确保该消息不会出现两次的方法是使用ID进行检查,比如说,如果该消息ID已在页面上,请不要再次添加它。我看到您在响应中已经有了一个ID,所以可以直接这样做您可能需要添加
t=setTimeout(getNewPosts(data.timestamp),1000)代码>因为您正在清除间隔清除间隔(t)在这之前,尝试setTimeout(function(){getNewPosts(data.timestamp)},1000)代码>非常感谢@fitype.Perfect solution,我只是想知道原因是否有解释?或者只是另一个javascript奇迹?