Avatar billede Slettet bruger
29. december 2007 - 15:38 Der er 37 kommentarer og
1 løsning

Javascript og AJAX script sløver server

Hej Eksperter.
Jeg har arbejdet lidt på en chat. For at undgå klik og blink, bruger jeg et javascript/ajax script. ¨
Jeg har skevet det sådan lidt random ud fra ting jeg har fundet på nettet, da jeg aldrig har lavet AJAX før,
Det virker som det skal, og jeg åbnede for chatten. Men efter noget tid, da der kom en del på af gangen, begyndte jeg at opleve at serveren blev sløvet TOTALT og jeg mistænker lidt scriptet for dette.
Scriptet ser således ud:

<script type="text/javascript" language="JavaScript">
function doLoad()
{
setTimeout( 'ajaxFunction() ',1*2000 );
}

function ajaxFunction()
{
var xmlHttp;
try
  {
  // Firefox, Opera 8.0+, Safari
  xmlHttp=new XMLHttpRequest();
  }
catch (e)
  {
  // Internet Explorer
  try
    {
    xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
  catch (e)
    {
    try
      {
      xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    catch (e)
      {
      alert("Your browser does not support AJAX!");
      return false;
      }
    }
  }
  xmlHttp.onreadystatechange=function()
    {
    if(xmlHttp.readyState==4)
      {
      Beskeden = xmlHttp.responseText;
      var temp = document.getElementById("Beskeder").innerHTML;
      document.getElementById("Beskeder").innerHTML=Beskeden+temp;

      }
    }
  xmlHttp.open("GET","skrivnyebesker.asp",true);
  xmlHttp.send(null);
  doLoad()
  }
</script>
</head>
<body bgcolor="white" onload="doLoad()">

skrivnyebesker.asp indeholder bare et kort asp script der tjekker om der er kommet nye beskeder siden sidst den blev kaldt.

Håber i kan hjælpe
Mvh
Bjarke
Avatar billede Slettet bruger
29. december 2007 - 15:42 #1
Det virker også somom at det sløver hele browseren også :-/ (Bruger FireFox, har ikke prøvet andre, men ved at hos andre er siden ihvertfald også sløv)
Avatar billede a1a1 Novice
29. december 2007 - 15:43 #2
setTimeout( 'ajaxFunction() ',1*2000 );

du venter 1*2000 millisek. (dvs 2000msek.) på at det går i gang

setTimeout( 'ajaxFunction() ',2000 ); (er fint 1*2000 giver 2000 ;o) )
Avatar billede erikjacobsen Ekspert
29. december 2007 - 15:43 #3
Hvis serveren bliver sløv er det indholdet af skrivnyebesker.asp der er problemet.
Avatar billede roenving Novice
29. december 2007 - 15:43 #4
Det, du viser afvikles jo på klienten, og kan derfor ikke sløve serveren !-)

-- men opdatering hvert andet sekund kan til gengæld sagtens sløve serveren ganske voldsomt, for er der f.eks. 50 brugere skal den jo behandle gennemsnitlig 25 requests pr. sekund, og afhængig af dit asp-script kan det lægge ganske store servere ned !o]

-- prøv at lave opdatering hvert 5. sekund, så skulle det hjælpe ganske meget !-)
Avatar billede w13 Novice
29. december 2007 - 15:44 #5
Jeg kan anbefale at skrivnyebeskeder.asp genererer outputtet i form af enten XML eller JSON.
Avatar billede Slettet bruger
29. december 2007 - 15:48 #6
w13 - ved ikke helt hvordan sådan noget fungerer, arbejder normalt kun med asp. Har du et eksempel, eller link til god guide til hvordan det skal bruges i en lignende situation?
Avatar billede Slettet bruger
29. december 2007 - 15:55 #7
Nu ved jeg godt det her er asp og vi er i javascript katagorien, men poster lige skrivnyebesker.asp så det måske er nemmere at komme med et forslag :)

<%
if session("Opdateringsid") <> "" then

Sql = "Select * from Beskeder where id > "& int(session("Opdateringsid")) &" order by id"
Set rs = conn.execute(sql)

Do until rs.eof
Besked = ""&rs("Besked")&"<br>"

session("Opdateringsid") = rs("id")

rs.movenext
Loop

else

End if
response.expires=-1
Response.write Besked

Conn.Close
Set Conn = Nothing
%>
Avatar billede w13 Novice
29. december 2007 - 16:27 #8
Ja, jeg ville lave json nogenlunde således:
------------------------------------------
<%response.contenttype="application/json"
response.expires=-1
if session("Opdateringsid")<>"" then

Set rs=conn.execute("Select * from Beskeder where id>"&int(session("Opdateringsid"))&" order by id")

Response.Write "{'message':["
Do until rs.eof
  Response.Write "'"&rs("Besked")&"',"
  session("Opdateringsid")=rs("id")

  rs.movenext
Loop
Response.Write "'']}"

End if

Conn.Close
Set Conn=Nothing%>
-------------------------------------------
Og så kan du i dit Ajax hente data sådan her:
-------------------------------------------
req.onreadystatechange=function(){
    if(req.readyState==4&&req.status==200){
        var json=eval("("+req.responseText+")");

        if(json.message.length>1){
            for(i=0;i<json.message.length){
                alert(json.message[i])
            }
        }
    };
};
Avatar billede w13 Novice
29. december 2007 - 16:27 #9
Forbehold for fejl! :)
Avatar billede w13 Novice
29. december 2007 - 16:38 #10
Ahr, skal vi sige sådan her:
------------------------------------------
<%response.contenttype="application/json"
response.expires=-1
if session("Opdateringsid")<>"" then

Set rs=conn.execute("Select * from Beskeder where id>"&int(session("Opdateringsid"))&" order by id")

Response.Write "{'message':["
i=0
Do until rs.eof
  If i>0 Then Response.Write ","
  Response.Write "'"&rs("Besked")&"'"
  session("Opdateringsid")=rs("id")
  i=i+1
  rs.movenext
Loop
Response.Write "]}"

End if

Conn.Close
Set Conn=Nothing%>
-------------------------------------------
Og Ajax-delen:
-------------------------------------------
req.onreadystatechange=function(){
    if(req.readyState==4&&req.status==200){
        var json=eval("("+req.responseText+")");

        if(json.message.length>0){
            for(i=0;i<json.message.length){
                alert(json.message[i])
            }
        }
    };
};
Avatar billede Slettet bruger
29. december 2007 - 17:15 #11
Er ikke helt sikker på hvad der skal ske i ajax delen er ikke så god til javascript.. men der magler da den del hvor den laver innterHTML?
Avatar billede w13 Novice
29. december 2007 - 17:19 #12
Ja, den er så en helt anden ting.

innerHTML er ugyldig kode, som kan resultere i fejl. Undgå, hvis muligt, altid innerHTML.
Det korrekte alternativ er DOM (Document Object Model).

Så ku' du evt. rette:
  alert(json.message[i])
til:
  document.getElementById('beskeder').appendChild(document.createTextNode(json.message[i]))

...hvor 'beskeder' er id'et på det element, der indeholder alle chatbeskeder.

Og så skal min kode bare erstatte koden:
  req.onreadystatechange=function(){
    ...
  };
Avatar billede Slettet bruger
29. december 2007 - 17:26 #13
hmmm nu har jeg gjort som du siger (tror jeg da :P..)
Men den siger bare: Du har valgt at åbne skrivenyebesker.asp og så kan man gemme den :S
Koden:
function ajaxFunction()
{
  xmlHttp.open("GET","skrivnyebesker.asp",true);
  xmlHttp.send(null);
  req.onreadystatechange=function(){
    if(req.readyState==4&&req.status==200){
        var json=eval("("+req.responseText+")");

        if(json.message.length>0){
            for(i=0;i<json.message.length){
                document.getElementById('beskeder').appendChild(document.createTextNode(json.message[i]))
            }
        }
    };
  };
  doLoad()
  }

Takker fordi du gider hjælpe mig, føler mig virkelig dum her ;)
Avatar billede w13 Novice
29. december 2007 - 17:33 #14
Jeg ved, at man kan få den gemme-dialogboks op, hvis man prøver at åbne skrivnyebesker.asp i vinduet, men når den loades med Ajax burde det da ikke være sådan.
Avatar billede Slettet bruger
29. december 2007 - 17:36 #15
ahh fandt fejlen til det ;)
Dog sker der ikke noget på chatten :(
Avatar billede Slettet bruger
29. december 2007 - 17:50 #16
Jeg har prøvet at lave en test der køre helt uden databaser osv:
http://bjarkes.dk/test

Men der sker ikke rigtig noget.
Koderne:
Index.asp
---------------
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" language="JavaScript">
function doLoad()
{
setTimeout( 'ajaxFunction() ',1*2000 );
}

function ajaxFunction()
{
  xmlHttp.open("GET","skrivnyebesker.asp",true);
  xmlHttp.send(null);
  req.onreadystatechange=function(){
    if(req.readyState==4&&req.status==200){
        var json=eval("("+req.responseText+")");

        if(json.message.length>0){
            for(i=0;i<json.message.length){
                document.getElementById('beskeder').appendChild(document.createTextNode(json.message[i]))
            }
        }
    };
  };
  doLoad()
  }
</script>
</head>

<body bgcolor="white" onload="doLoad()">


<div id="Beskeder" class="chat"></div>

</body>
</html>
------------------
skrivnyebesker.asp
------------------
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%response.contenttype="application/json"
response.expires=-1
Response.Write "{'message':["
Response.Write "'Hej',"
Response.Write "'']}"
%>
</body>
</html>

Men der sker intet
Avatar billede w13 Novice
29. december 2007 - 18:01 #17
Jeg ser umiddelbart 2 fejl.

Den første er kun lidt vigtig, da den ikke nødvendigvis giver en fejl på siden: <div id="Beskeder"> skal være <div id="beskeder">
Altså med lille "b", da det er med lille forbogstav oppe i vores javascript-del.

Den anden (meget store) fejl:
skrivnyebesker.asp må ikke indeholde HTML!
Så den skal være:
------------------
<%response.contenttype="application/json"
response.expires=-1
Response.Write "{'message':['Hej']}"%>
Avatar billede Slettet bruger
29. december 2007 - 18:13 #18
hmm det er rettet, men der kommer ingen hej´er frem :(
Avatar billede w13 Novice
29. december 2007 - 18:39 #19
Du bør slå "Meddelelser om JavaScript-fejl" til, når du koder JavaScript. Så kommer den op med advarsler. Bl.a. "; var ventet" og "objekt var ventet", samt disse fejls linjenr.

Første fejl er linjen:
            for(i=0;i<json.message.length){
som skal være:
            for(i=0;i<json.message.length;i++){
Den smuttede lige for mig.

Anden fejl er, at du (2 steder" kalder funktionen DoLoad(), som tilsyneladende ikke findes nogen steder?
Avatar billede w13 Novice
29. december 2007 - 18:40 #20
Jo okay, DoLoad() fandtes. Hmm, mærkeligt.
Avatar billede w13 Novice
29. december 2007 - 18:42 #21
Ret lige:
  function doLoad()
  {
    setTimeout( 'ajaxFunction() ',1*2000 );
  }
Til:
  function doLoad(){
    setTimeout("ajaxFunction()",2000)
  }
Avatar billede Slettet bruger
29. december 2007 - 19:30 #22
ja okay kan godt se at det er praktisk at se fejlen ;)
Nu siger den at req ikke er defineret hvilket egentlig er rigtig nok.
req.onreadystatechange=function(){
Det req bliver ikke beskrevet nogen steder
Avatar billede Slettet bruger
29. december 2007 - 19:36 #23
Doh, det var jo det der var fejlen, du brugte req og jeg definerede det som xmlHttp
Avatar billede w13 Novice
29. december 2007 - 19:40 #24
:) Jep. Så virker eksemplet, kan jeg se.
Avatar billede Slettet bruger
29. december 2007 - 19:43 #25
Nu ved jeg om jeg strammer den, men det jeg brugte før var lavet sådan at hvis det den hentede var html så skrev den det som html, og jeg bestemte også hvor teksten skulle komme, før eller efter det gamle tekst. Disse ting er rimelig væsentlige i en chat :-/
Kender du en løsning på dettte med json?
Avatar billede w13 Novice
29. december 2007 - 19:46 #26
Det er "ulempen" ved at bruge DOM i stedet for innerHTML - man skal selv bygge tingene i stedet for at indsætte det hele på én gang.

Ang. at indsætte før den gamle tekst, så brug:

document.getElementById('beskeder').insertBefore(document.getElementByid('beskeder').firstChild,document.createTextNode(json.message[i]))

Hvis du beskriver, hvordan beskeden skal indsættes som HTML, kan jeg muligvis hjælpe.
Avatar billede Slettet bruger
29. december 2007 - 19:53 #27
document.getElementById('beskeder').insertBefore(document.getElementByid('beskeder').firstChild,document.createTextNode(json.message[i]))
Giver
Linje: 73
Teng: 5
Objektet understøtter ikke denne egenskab eller metode
linje 73 er:
var json=eval("("+xmlHttp.responseText+")");

Eksempel på en besked:
<font color="Black">19:52 <b>Bjarke</b>: hejsa</font>
Avatar billede w13 Novice
29. december 2007 - 20:19 #28
Wups, getElementByid skal være getElementById

JavaScript er jo Case Sensitive.

Jeg bliver nødt til at smutte nu, men kigger på det igen, senere i aften eller i morgen tidlig.
Avatar billede Slettet bruger
29. december 2007 - 20:25 #29
Takker mange gange :D
Jeg kan godt oprette et ny spørgsmål, da det jo i princippet er et nyt spørgsmål... Så kan du få flere points hvis det er, men ihvertfald er jeg uendelig glad for de hjæld indtil nu :)
Avatar billede w13 Novice
30. december 2007 - 13:05 #30
Takker for point! :)

Er du fri for fejlen nu eller hvordan?
Avatar billede Slettet bruger
30. december 2007 - 13:48 #31
Der er fejl ved den der "den anden vej" kode, men det er nu ikke så vigtigt, så kan jeg bare fjerne så brugeren selv kan vælge retning.

Men det der med HTML´en, har jeg ikke fundet ud af
Avatar billede w13 Novice
30. december 2007 - 14:00 #32
Ok. Altså lige nu genererer du for eksempel:

{'message':['Hello','world','!']}

Hvis du nu gør således i stedet:

{'message':[
  {'tid':'19:52','navn':'Bjarke','besked':'Hello'},
  {'tid':'19:53','navn':'Ulla','besked':'world'},
  {'tid':'20:05','navn':'Bjarke','besked':'!'}
]}

Så kan du hente disse data med:

json.message[i].tid
json.message[i].navn
json.message[i].besked

Det er jo vildt smart. =)

Og så erstatter du:
  document.getElementById('beskeder').appendChild(document.createTextNode(json.message[i]))

Med nogenlunde følgende:
  document.getElementById('beskeder').appendChild(document.createElement('font'));
  document.getElementById('beskeder').lastChild.style.color="black";
  document.getElementById('beskeder').lastChild.appendChild(document.createTextNode(json.message[i].tid+' '));
  document.getElementById('beskeder').lastChild.appendChild(document.createElement('b'));
  document.getElementById('beskeder').lastChild.lastChild.appendChild(document.createTextNode(json.message[i].navn));
  document.getElementById('beskeder').lastChild.appendChild(document.createTextNode(': '));
  document.getElementById('beskeder').lastChild.appendChild(document.createTextNode(json.message[i].besked));
Avatar billede w13 Novice
30. december 2007 - 14:04 #33
Der kan dog spares et par linjer, hvis du ikke har noget imod, at koden bli'r
<font style="color:black"><b>19:52 Bjarke:</b> Hejsa</font><br>

Så bliver min kode:
  document.getElementById('beskeder').appendChild(document.createElement('font'));
  document.getElementById('beskeder').lastChild.style.color="black";
  document.getElementById('beskeder').lastChild.appendChild(document.createElement('b'));
  document.getElementById('beskeder').lastChild.lastChild.appendChild(document.createTextNode(json.message[i].tid+' '+json.message[i].navn+':'));
  document.getElementById('beskeder').lastChild.appendChild(document.createTextNode(' '+json.message[i].besked));
  document.getElementById('beskeder').appendChild(document.createElement('br'));
Avatar billede Slettet bruger
30. december 2007 - 14:59 #34
Kan jeg f.eks. gøre således:

{'message':[
  {'farve':'"&farve&"','tid':'"&tid&"','navn':'"&navn&"','besked':'"&besked&"'}
]}

og  document.getElementById('beskeder').appendChild(document.createElement('font'));
  document.getElementById('beskeder').lastChild.style.color=document.createTextNode(json.message[i].farve+');
  document.getElementById('beskeder').lastChild.appendChild(document.createElement('b'));
  document.getElementById('beskeder').lastChild.lastChild.appendChild(document.createTextNode(json.message[i].tid+' '+json.message[i].navn+':'));
  document.getElementById('beskeder').lastChild.appendChild(document.createTextNode(' '+json.message[i].besked));
  document.getElementById('beskeder').appendChild(document.createElement('br'));

Altså for at tilføje forskellig farve?

Et andet problem, er at den replacer alle :),:D,;) osv, med billeder :S
Og der er nogle funktioner til at lave links, hvilket er noget af det vigtigste
Hvis man skriver /p så kommer der et link.. :(

Ved godt jeg er problematisk ;)
Avatar billede w13 Novice
30. december 2007 - 15:05 #35
Ja, det kan jeg godt se, er lidt skidt.. Hmm.. Jeg er blank.. Hmmmmmm.. Det kan selvfølgelig laves, men det vil godt nok kræve meget..

Måske skal vi gå tilbage til innerHTML så.. =(

Så skal du bare generere beskederne sådan her:
{'message':['<font color="black">19:52 <b>Bjarke</b>: Hejsa</font>']}

og indsætte med innerHTML:
document.getElementById("beskeder").innerHTML+=json.message[i];
Avatar billede olebole Juniormester
02. januar 2008 - 15:25 #36
<ole>

Hvis problemet er server-belastning, så udryd alle stjerner (*) i dine DB-kald (med mindre du virkelig skal bruge _alle_ felterne) - og sørg for ordentlig indeksering af dine DB-tabeller

/mvh
</bole>
Avatar billede w13 Novice
02. januar 2008 - 15:52 #37
Hvad var det en kommentar til, Ole? :)
Avatar billede erikjacobsen Ekspert
02. januar 2008 - 18:31 #38
Jeg tror Ole refererer til spørgerens oprindelige problem, at det belaster serveren. Om man (mis)bruger innerHTML, eller leverer perfekt XML/JSON/whatever gør jo ikke nogen forskel på det.

Eneste brugbare svar i den anledning i dette spørgsmål, har vel være at nøjes med at spørge hvert 5 sekund i stedet for hver andet.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester