2012-10-09 49 views
10

Escribí un pequeño complemento de chat que necesitaré usar en mi sitio. Funciona con una estructura simple en HTML, así:Problema de Chrome: las líneas de chat devuelven varias veces

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

Hay un 'clic' evento obligado en ese elemento Span, por supuesto. Entonces, cuando el usuario introduce un mensaje y hace clic en el "Enviar" elemento span, hay una función de Javascript con las llamadas de un evento Ajax que inserta el mensaje en la base de datos MySQL:

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

Y, en caso de que el mensaje es insertado con éxito en la base de datos, se llama a una función para leer nuevas líneas y ponerlas en estructura HTML que he publicado antes:

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

Nota: 'ajax_result' sólo contiene entidades HTML, caracteres no especiales, por lo que incluso si un mensaje contiene '> + <', está codificado por el script php llamado con Ajax, antes de ser procesado desde esta función JS.

Ahora, viene el comportamiento extraño: cuando envíen nuevos mensajes Opera, Firefox e incluso IE8 funciona bien, como se pretende, de esta manera:

A screen taken from Firefox

Pero, cuando abro la ventana Chrome, veo esto :

A screen taken from Chrome

Como se puede ver, en Chrome se muestran los mensajes varias veces (cada vez mayor el número cada vez, hasta 8 líneas por mensaje). Comprobé el visor de depuración interno y no parece que se llame a la función "leer líneas nuevas" más de una vez, por lo que debería ser algo relacionado con los eventos de Jquery, o algo más.

esperanza que he sido claro en mi explicación, en caso de necesitar cualquier otra cosa, que me haga saber :)

Gracias, Erenor.

EDITAR

Como ha señalado Shusl, se me olvidó mencionar que la función function_get_newchatlines() se llama, de forma periódica, por un setInterval(function_get_newchatlines, 2000) en Javascript.

Edit2

Aquí es una tira del código del archivo PHP llamado por Ajax para obtener nuevas líneas de chat (no creo que cosas como "session_start()" o cosas por el enlace con MySQL son necesarios aquí)

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

de todos modos, creo que, si el problema era este script PHP, me gustaría tener errores similares en otros navegadores, también :)

EDIT4

Aquí está el código que se une al evento click a la opción "Enviar" elemento span:

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

(Gracias a f_puras para añadir la etiqueta falta :)

+1

¡Pregunta interesante! – Mattis

+0

¿Cómo estás decidiendo qué líneas de chat ya se enviaron al cliente? Estoy haciendo esta pregunta porque no veo ninguna marca de tiempo en la comunicación. – Anoop

+0

Uh ... gracias ... me encantaría algunas respuestas interesantes, también él: D –

Respuesta

2

lo haría uno de los siguientes:

opción

1:

detener el temporizador antes de la llamada AJAX en function_write_newchatline() e iniciar el t imer cuando vuelve la llamada ajax. opción

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:

No Llamar function_get_newchatlines() en absoluto en el caso de éxito de la llamada AJAX. Permita que solo el temporizador recupere las entradas de chat.

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

Me parece que una condición de carrera entre los function_get_newchatlines() que se llama después de una entrada de chat se añade por el usuario y la llamada periódica de function_get_newchatlines() por el temporizador.

opción 3:

Uso setTimeout en lugar de setInterval. setInterval puede complicar las cosas cuando el navegador está ocupado. Entonces, al final de la función setTimeout, vuelva a llamar a setTimeout.

+0

Gracias por la respuesta. Esas fueron las soluciones que probé antes, incluso con una pequeña diferencia: Opción 1: utilicé setTimeout en el resultado 'completo' (incluso si hubiera un error, se realizaría una nueva solicitud después de 2 segundos) Opción 2: al insertar un nuevo línea, el usuario tendría que esperar (en el peor de los casos) 2 segundos antes de ver su línea, pensé que no era bueno :) –

+0

De todos modos, descubrí que puedo crear una solución para evitar que las funciones se llamen dos veces (o más) utilizando una "variable de seguridad" que debe verificarse antes de llamar a la función para leer nuevas líneas. Esto oculta los síntomas, pero no me dice dónde está exactamente el problema. Desafortunadamente :( –

+0

Se agregó una tercera opción. Verifíquelo –

Cuestiones relacionadas