10

サイトで使用する必要がある小さなチャット プラグインを作成しました。次のように、HTML の単純な構造で動作します。

<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>

もちろん、その Span 要素には「クリック」バインド イベントがあります。次に、ユーザーがメッセージを挿入して「送信」スパン要素をクリックすると、メッセージを MySQL データベースに挿入する Ajax イベントを呼び出す Javascript 関数があります。

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

そして、メッセージがDBに正常に挿入された場合、関数を呼び出して新しい行を読み取り、前に投稿したHTML構造に配置します:

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

注: 「ajax_result」には特別な文字ではなく、html エンティティのみが含まれるため、メッセージに「>+<」が含まれていても、この JS 関数から処理される前に、Ajax で呼び出される php スクリプトによってエンコードされます。

ここで、奇妙な動作が発生します。新しいメッセージを投稿するとき、Opera、Firefox、さらには IE8 でさえ、意図したとおりに次のようにうまく動作します。

Firefox から取得した画面

しかし、Chrome ウィンドウを開くと、次のように表示されます。

Chrome から取得した画面

ご覧のとおり、Chrome ではメッセージが複数回表示されます (メッセージごとに最大 8 行まで、回数が増えるたびに増加します)。内部デバッグ ビューアーを確認したところ、「新しい行を読み取る」関数が複数回呼び出されているようには見えないため、Jquery イベントに関連するものか、それ以外のものである必要があります。

説明が明確であることを願っています。他に何か必要な場合はお知らせください:)

ありがとう、エレノア。

編集

Shusl が指摘したように、この関数はJavascriptfunction_get_newchatlines()によって定期的に呼び出されることを忘れていました。setInterval(function_get_newchatlines, 2000)

EDIT2

これは、新しいチャット行を取得するために Ajax によって呼び出される PHP ファイルからのコードの一部です (「session_start()」や mysql 接続などはここでは必要ないと思います)。

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

とにかく、問題がこの PHP スクリプトである場合、他のブラウザーでも同様のエラーが発生すると思います :)

EDIT4

クリック イベントを "Send" スパン要素にバインドするコードは次のとおりです。

$('#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
});

(不足しているタグを追加してくれた f_puras に感謝します :)

4

1 に答える 1

2

次のいずれかを行います。

オプション1:

function_write_newchatline() で ajax 呼び出しの直前にタイマーを停止し、ajax 呼び出しが戻ったときにタイマーを開始します。

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

オプション 2:

ajax 呼び出しの成功イベントで function_get_newchatlines() をまったく呼び出さないでください。タイマーだけがチャット エントリを取得できるようにします。

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

ユーザーがチャット エントリを追加した後に呼び出される function_get_newchatlines() と、タイマーによる定期的な function_get_newchatlines() の呼び出しとの間に競合状態があると思います。

オプション 3:

setInterval の代わりに setTimeout を使用します。setInterval は、ブラウザがビジー状態のときに混乱する可能性があります。そのため、setTimeout 関数の最後で setTimeout を再度呼び出します。

于 2012-10-09T16:40:43.687 に答える