Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome issue - chat lines return multiple times

I wrote a little chat plugin that i'll need to use on my site. It works with a simple structure in HTML, like this:

<div id="div_chat">
  <ul id="ul_chat">
  </ul>
</div>

<div id="div_inputchatline">
  <input type="text" id="input_chatline" name="input_chatline" value="">
  <span id="span_sendchatline">Send</span>
</div>

There's a 'click' bound event on that Span element, of course. Then, when the user inserts a message and clicks on the "Send" span element, there's a Javascript function with calls an Ajax event that inserts the message into the MySQL database:

function function_write_newchatline()
{
  var chatline = $('#input_chatline').val();

  $.ajax
  ({
    type: "POST",
    url: "ajax-chat-writenewline.php", //1: ok, 0: errore
    data: ({'chat_line': chatline}),
    dataType: "text",
    cache: false,
    success: function(ajax_result)
    {
      function_get_newchatlines();
    }
  });
}

And, in case the message is successfully inserted into DB, it calls a function to read new lines and put them in HTML structure i posted before:

function function_get_newchatlines()
{
  $.ajax
  ({
    type: "POST",
    url: "ajax-chat-loadnewlines.php", //1: ok, 0: errore
    data: '',
    dataType: "text",
    cache: false,
    success: function(ajax_result) //example of returned string: 'message1>+<message2>+<message3'
    {
      //explode new chat lines from returned string
      var chat_rows = ajax_result.split('>+<');
      for (id_row in chat_rows)
      {
        //insert row into html
        $('#ul_chat').prepend('<li>' + chat_rows[id_row] + '</li>');
      }
      $('#span_sendchatline').html('Send');
    }
  });
}

Note: 'ajax_result' only contains html entities, not special chars, so even if a message contains '>+<', it is encoded by the php script called with Ajax, before being processed from this JS function.

Now, comes the strange behaviour: when posting new messages Opera, Firefox and even IE8 works well, as intended, like this:

A screen taken from Firefox

But, when i open Chrome window, i see this:

A screen taken from Chrome

As you can see, in Chrome the messages are shown multiple times (increasing the number each time, up to 8 lines per message). I checked the internal debug viewer and it doesn't seem that the "read new lines" function is called more than one time, so it should be something related to Jquery events, or something else.

Hope i've been clear in my explanation, should you need anything else, let me know :)

Thanks, Erenor.

EDIT

As pointed out by Shusl, i forgot to mention that the function function_get_newchatlines() is called, periodically, by a setInterval(function_get_newchatlines, 2000) into Javascript.

EDIT2

Here's is a strip of the code from the PHP file called by Ajax to get new chat lines (i don't think things like "session_start()" or mysql connection stuff are needed here)

//check if there's a value for "last_line", otherwise put current time (usually the first time a user logs into chat)
if (!isset($_SESSION['prove_chat']['time_last_line']) || !is_numeric($_SESSION['prove_chat']['time_last_line']) || ($_SESSION['prove_chat']['time_last_line'] <= 0))
{
  $_SESSION['prove_chat']['time_last_line'] = microtime(true);
}

//get new chat lines
$result = mysql_query("select * from chat_module_lines where line_senttime > {$_SESSION['prove_chat']['time_last_line']} order by line_senttime asc; ", $conn['user']);
if(!$result || (mysql_num_rows($result) <= 0))
{
  mysql_close($conn['user']); die('2-No new lines');
}
//php stuff to create the string
//....
die($string_with_chat_lines_to_be_used_into_Javascript);

Anyway, i think that, if the problem was this PHP script, i would get similar errors in other browsers, too :)

EDIT4

Here's the code that binds the click event to the "Send" span element:

$('#span_sendchatline').on('click', function()
{
  //check if there's already a message being sent
  if ($('#span_sendchatline').html() == 'Send')
  {
    //change html content of the span element (will be changed back to "send"
    //when the Ajax request completes)
    $('#span_sendchatline').html('Wait..');
    //write new line
    function_write_newchatline();
  }
  //else do nothing
});

(Thanks to f_puras for adding the missing tag :)

like image 886
Erenor Paz Avatar asked Oct 09 '12 11:10

Erenor Paz


1 Answers

I would do one of the following:

option 1:

stop the timer just before the ajax call in function_write_newchatline() and start the timer when the ajax call returns.

function function_write_newchatline()
{
  var chatline = $('#input_chatline').val();

  stop_the_timer();
  $.ajax
  ({
    type: "POST",
    url: "ajax-chat-writenewline.php", //1: ok, 0: errore
    data: ({'chat_line': chatline}),
    dataType: "text",
    cache: false,
    success: function(ajax_result)
    {
      function_get_newchatlines();
    },
    complete: function() {
      start_the_timer();
    }
  });
}

option 2:

Not call function_get_newchatlines() at all in the success event of the ajax call. Let only the timer retrieve the chat entries.

function function_write_newchatline()
{
  var chatline = $('#input_chatline').val();

  $.ajax
  ({
    type: "POST",
    url: "ajax-chat-writenewline.php", //1: ok, 0: errore
    data: ({'chat_line': chatline}),
    dataType: "text",
    cache: false,
    success: function(ajax_result)
    {
      // do nothing
    }
  });
}

I think there is some race condition between the function_get_newchatlines() that is called after a chat entry is added by the user and the periodical call of function_get_newchatlines() by the timer.

option 3:

Use setTimeout instead of setInterval. setInterval can mess things up when the browser is busy. So in the end of the setTimeout function call setTimeout again.

like image 94
Yoni Baciu Avatar answered Oct 22 '22 19:10

Yoni Baciu