IBGDB
Die Indie Browsergame Datenbank - Unabhängig & Ehrlich.
you are not logged in
Login

Problem beim Reload (mit jQuery) des Chats bleibt die Seite "kurz" hängen

WedPMCESTECEST1AugE
Problem beim Reload (mit jQuery) des Chats bleibt die Seite "kurz" hängen  

 

Hallo zusammen,

ich habe ein sehr ärgerliches Problem und kann mir nicht so recht erklären, woher es kommt. Auch nach 2 Tagen Google-Befragung bin ich nicht wirklich weiter und hoffe, dass vielleicht einer von euch schon mal mit dem Problem zu kämpfen hatte und einen Tipp für mich hat. Wir haben bei unseren Games einen Chat eingebaut, dessen Inahlt aus einer XML, die auf unserem Server liegt, geladen wird. Dafür nutzen wird jQuery.ajax. Es funktioniert auch alles soweit. Jedoch kann man auf der Webseite eindeutig kleine (mit Chrome und guter Hardware) bis zu richtig heftige Verzögerungen (u.a. im FF) feststellen, wenn alle 1,5 Sekunden der Reload erfolgt. Dies ist z.B. sehr gut spürbar, wenn man gerade einen Text schreibt und die Buchstaben einen Moment verzögert kommen oder das Scrollen auf der Seite kurz hängen bleibt. Ich bin wirklich ratlos, was schiefläuft, schließlich lassen wir alles asynchron ausführen. :-( ...schalte ich den Chat aus, läuft die Seite wieder absolut flüssig. 

 

Ich kopiere hier mal die relevanten Codeteile rein. 

 

 

function StartChat() { if(sessionStorage.chatOpen == 1) { jQuery.ajax({url: "chat/90m.xml",dataType:'xml',type: 'GET',async: true, cache: false, success: function(data) { var cnt = 0; jQuery(data).find('chat').find('message').each(function() { var textMessage = jQuery(this).find('messageText').text().replace(';-)', '<img src="../img/smilieWink.gif" />') textMessage = textMessage.replace(':)','<img src="../img/smilieSmile.gif" />'); textMessage = textMessage.replace(':-)','<img src="../img/smilieSmile.gif" />'); textMessage = textMessage.replace(':D','<img src="../img/smilieFatSmile.gif" />'); textMessage = textMessage.replace(':-D','<img src="../img/smilieFatSmile.gif" />'); textMessage = textMessage.replace(':(','<img src="../img/smilieSad.gif" />'); textMessage = textMessage.replace(':-(','<img src="../img/smilieSad.gif" />'); textMessage = textMessage.replace(';-(','<img src="../img/smilieFrown.gif" />'); textMessage = textMessage.replace('?-(','<img src="../img/smilieConfused.gif" />'); textMessage = textMessage.replace(':-O','<img src="../img/smilieEek.gif" />'); textMessage = textMessage.replace(':-p','<img src="../img/smilieTongue.gif" />'); textMessage = textMessage.replace('8-)','<img src="../img/smilieCool.gif" />'); textMessage = textMessage.replace(':lol:','<img src="../img/smilieLol.gif" />'); textMessage = textMessage.replace(':CC:','<a href="http://www.culture-conflicts.net" target="_blank">Culture-Conflicts.net</a>'); if (textMessage.indexOf('[wiki]') != -1 && textMessage.indexOf('[/wiki]') != -1) { var wikiName = textMessage.substring(textMessage.indexOf('[wiki]') +6, textMessage.indexOf('[/wiki]')); textMessage = textMessage.replace('[wiki]','<a href="http://93.186.160.152/wiki/DE/index.php/'); textMessage = textMessage.replace('[/wiki]','" target="_blank">' + wikiName + '</a>'); } if(thisObj.lastChatMessageID <=  parseInt(jQuery(this).find('messageID').text()) && thisObj.lastChatMessageID != 0) { var newText = ''; newText += '<span style="text-decoration:underline;cursor:pointer;" onclick="window.location=\'http://www.90-minutes.org/clubOverview.asp?infoTeamID=' + jQuery(this).find('teamID').text() + '\'">' + jQuery(this).find('userName').text() + '</span>' + ': '  + textMessage + '<br /><span style="font-style:italic;">(' + jQuery(this).find('messageDateTime').text() + ')</span>' + '<br /><br />'; jQuery('#chatText').html(newText); } else { var newText = jQuery('#chatText').html(); newText += '<span style="text-decoration:underline;cursor:pointer;"  onclick="window.location=\'http://www.90-minutes.org/clubOverview.asp?infoTeamID=' + jQuery(this).find('teamID').text() + '\'">' + jQuery(this).find('userName').text() + '</span>' + ': '  + textMessage + '<br /><span style="font-style:italic;">(' + jQuery(this).find('messageDateTime').text() + ')</span>' + '<br /><br />'; jQuery('#chatText').html(newText); } if(parseInt(jQuery(this).find('messageID').text()) > thisObj.highestChatMessageID) { thisObj.highestChatMessageID = parseInt(jQuery(this).find('messageID').text()); } cnt++; }); thisObj.lastChatMessageID = thisObj.highestChatMessageID; jQuery('#chatTextNewDiv').css('visibility','hidden'); jQuery('#sendingChatTextImageDiv').css('display','none'); jQuery('#chatText').css('height','245px'); window.setTimeout("StartChat()", 1500); }}); } }

 

 

 

jQuery('#chatDrag').click(function() { if(jQuery('#chatMainDiv').css('display') == 'none') { jQuery('#chatDiv').css('height','300px'); jQuery('#chatMainDiv').css('display','block'); sessionStorage.chatOpen = 1; window.setTimeout("StartChat()", 1000); } else { jQuery('#chatDiv').css('height','20px'); jQuery('#chatMainDiv').css('display','none'); sessionStorage.chatOpen = 0; } });     Ich denke, das sind wohl die beiden relevantesten Codestellen. Den ganzen Rest drumrum lasse ich erstmal weg, um euch zu viel Lesen zu ersparen. :-)  Es wäre super klasse, falls jemand hier einen Idee hat?   Viele Grüße, Marius  
ThuAMCESTECEST1AugE
 

aalso generell gilt bei jQuery dass man vorher den DOM selektiert. in deinem Fall wird das gesammte DOM alle 1.5 sekunden durchsucht nach bestimmten elementen.

estmal zum anfang. bei deinem chat würde ich es so machen

var chatIsActive = false;

var interval = null;

$('#chatfenster').on('click',function(){

if(chatIsActive && interval) {

window.clearTimeout(interval)

}else{

chatIsActive = true;

interval = window.setTimeout(read,1500);

}

});

die read funktion würde dann so in etwa aussehen

var read = function(){

$.ajax({

url:'deine_datei.json',

dataType:'json',

success:function(data){

display(data);

}

})

}

 

dann sehe ich, dass du im chat durch jedes element durchläufst und die smylies in img src umwandelst. stattedessen wäre es sinnvoller den gelesenen text einmal umzuwandeln und den resultierenden html code in dein chat zu schreiben.

each funktion ist unter anderem auch ein perofrmance killer

statt indexOf wiki würde ich einen regulären ausdruck in js verwenden. kannst dir mal den quellcode vom BB plugin des Ckeditors anschauen, die suchen auch nur nach [b]text[/b] und ersetzen es.

dann sehe ich dass du onclick inline even verwendest, da würde ich eher für deine nachrichten ein ul li konstrukt verwenden

<ul>

<li class="user" id="user_id"><span class="username"></span><span class="message"></span></li>

</ul>

die styles in CSS einbauen und kein onclick beim usernamen, stattdessen jquery live verwenden außerhalb von success callback von ajax

$('.username').live('click',function(){

var me = $(this);

var user_id = me.parent('li').attr('class');

var user_name = me.attr('class');

});

 

und statt xml würde ich dir json empfehlen. habe deine xml code angeschaut ich würde eher eine php vernwenden die json objekt zurückliefert

<?php

//lesen der nachrichten

$result = array();

foreach($messages as $message){

$result [] = array(

'user_id' => $message['user_id'],

'user_name' => $message['user_name'],

'message'=>$message['message'],

'time' => $message['time']

);

}

echo json_encode($result);

 

der vorteil daran wäre dass du in success des ajax requests, ledeglich die daten über . notation ansprechen könntest

success:function(data){

console.log(data[0].user_id);

}

dadurch würde bei dir sowas wie jQuery(data) komplett wegfallen, denn es kostet auch etwas zeit um aus den daten ein jquery objekt zu generieren.

 

und zu guter letzt würde ich noch einen zeitstempel im ajax request mitversenden, so dass du die nachrichten der letzten 10 minuten oder so anzeigst und nicht alle nachrichten, um die daten gering zu halten.

 

wenn du alerdings ein vServer hast, da würde ich einfach über die console nodeJS installieren, npm installieren. danach mit dem npm now installieren und forever installieren. danach diesen quellcode in dein spiel einbauen http://nowjs.com/examples/hw  und schon haste ein chat, welches nur dann aktualisiert wenn wirklich neue daten dazukommen.

MFG

ThuAMCESTECEST1AugE
 

Hi BlackScorp, 

 

erstmal tausend Dank für deine ausführliche Antwort. Ich muss mich mit Dennis kurz schließen, um deine Vorschläge anzugehen bzw. die richtigen Schlüsse daraus zu ziehen. Er ist der fitter Webentwickler von uns beiden. :-)

 

Viele Grüße,

Marius

 

ThuAMCESTECEST1AugE
 

BlackScorp , Scorp ist gekürzt für Skorpion :P

ThuAMCESTECEST1AugE
 

Hallo BlackScorp,

 

ich muss mal blöd zu der Aussage mit der Selektion der gesamten DOM alle 1,5 Sek. fragen und vorab zugeben, dass ich da ziemlich schimmerlos bin. :-)

 

Du schreibst, dass bei uns die gesammte DOM alle 1,5 Sekunden durchsucht wird. Aber in deinem Beispiel sprichst du doch auch, wie wir das Chatfenster normal an: $('#chatfenster')... wir machen das an den nötigen Stellen z.B. so jQuery('#chatText').html(newText); . Ich sehe da nicht den Unterschied oder stehe vermutlich nur ganz blöd auf der Leitung. Wenn du mir dazu noch etwas sagen könntest oder einen Link hast, der einem Dummy wie mir hilft, die vorhanden Wissenslücken zu schließen, wäre ich dir sehr dankbar. Die Googlesuche hat mir noch nicht wirklich die richtige Erläuchtung gebracht. Wenn ich z.B. hier schaue, wird auch alles nur über den Namen aus de CSS angesprochen: http://www.fh-wedel.de/~si/seminare/ws09/Ausarbeitung/07.jquery/domSelection.html

Viele Grüße,

Marius

ThuAMCESTECEST1AugE
 

was ich damit sagen wollte ist, dass man am anfang selektiert und das ergebnis in variable zwischenspeichert.

 

var chatfenster = $('#chatfenster'); //element gefunden jquery objekt zwischengespeichert

 

//irgendwo in success ..

chatfenster.html(text); //muss nicht mehr neu gesucht werden ,weil schon davor gefunden

 

dieses $('#chatfenster') das geht durch den DOM baum und sucht nach id, es ist zwar schnell aber es ist unnötig jedesmal zu suchen, es reicht wenn man es einmal gemacht hat und dann immer wieder das gefundene ergebnis verwendet

hier gibt es paar ansätze

http://www.artzstudio.com/2009/04/jquery-performance-rules/

 

was mir noch aufgefallen ist, dass ihr auch prüft ob bereits text in der chatbox drin steht, wenn ja dann holt ihr den html code und hängt neuen text dran und schreibt den neuen html code rein.

für solche fälle gibt es die append methode

var text  = $('#text');

 

text.append('<li>Test</li>');

append hängt immer zum schluss weiteren code dran, prepend hängt ein code davor

ThuAMCESTECEST1AugE
 

Hey, super vielen Dank für die Aufkärung. Ich glaube wir verwenden fast überall die beschriebene Vorgehensweise. D.h. wir sollten am besten durch den ganzen Code durch und überall, wo DIVs & Co. angesprochen werden, diese einmalig beim Laden der Seite in eine Variablen schreiben und dann überall, wo das jeweilige Element angesprochen wird, die jeweilige Variable einsetzen. Vielleicht hilft uns das ja sogar grundsätzlich die Performance der Seite zu verbessern.

 

Viele Grüße,

Marius