2014-11-02 41 views
1

我目前正在用日誌輪詢構建一個聊天應用程序。 原型位於:http://chat.alexanderjank.de長時間投票:爲什麼有些消息會進來兩次?

在服務器端使用PHP。但我認爲這是一個javascript問題,有些消息會出現幾次。

所使用的JavaScript代碼:

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); 
}); 

請幫我解決這個問題。保證消息不會出現兩次

+0

BTW:這是_normal polling_,而不是[long polling](http://en.wikipedia.org/wiki/Push_technology#Long_polling) – hindmost 2014-11-02 09:31:16

+0

@ behindmost不在服務器端。服務器保持連接處於打開狀態,直到通過每秒輪詢數據庫從數據庫獲得新消息。但它以心跳關閉了連接,但它在15秒內沒有收到一條新消息。 – jankal 2014-11-02 09:35:49

+1

確保它不會出現兩次的方法是使用ID來檢查,​​如果此消息ID已在頁面上,則不要再次添加它。我看到你在回覆中已經有了一個ID,所以這樣做會非常簡單。 – Filype 2014-11-02 09:41:53

回答

2

一種方法是使用一個ID,以檢查在DOM該消息的存在,循環功能中,你已經有了:

$.each(data.posts, function(index, val) { 
    if(!$('#message-'+val.id).length) { 
     // Add message to the DOM 
    } 
}); 

如果消息是已經在DOM中,它不會再被添加。我看到你在回覆中已經有了一個ID,所以這樣做會非常簡單。

+0

非常感謝@Filype。 – jankal 2014-11-02 22:13:28

+1

完美的解決方案,即時通訊只是好奇,如果一個解釋被認識到的原因?或者只是另一個JavaScript奇蹟? – Pogrindis 2014-11-03 00:54:01

相關問題