[javascript] setTimeout() werkt niet

Pagina: 1
Acties:

  • Johnny
  • Registratie: December 2001
  • Laatst online: 22-05 10:01

Johnny

ondergewaardeerde internetguru

Topicstarter
Ik heb hier een klein stuke javascript dat een willekeurig element uit een array haalt, het op de pagina laat zien, een tijdje wacht en vervolgens weer een willekeurig element kiest en laat zien.

Het script werkt de eerste keer goed, maar zodra het wachten voorbij is krijg ik in MSIE een foutmelding dat op regel 1, teken 1 het object 'aa' niet kan worden gevonden. Op die positie staat er natuurlijk helemaal geen javascript code. 'aa' is de inhoud van het tweede element van de array, hoe hij daar bij komt weet ik niet.

Hier staat een testpagina.

In Mozilla werkt het ook maar een enkele keer, maar daar krijg ik geen foutmelding.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • mjax
  • Registratie: September 2000
  • Laatst online: 14-05 11:00
Volgens mij ontstaat dit probleem, omdat de parameter 'ad' (waar je array in meegegeven wordt) na afloop van de functie setAd() uit de scope loopt (het is tenslotte slechts een parameter van die functie. 1 seconde later gaat die setTimeout() af, die nog steeds een verwijzing naar die parameter bevat, maar inmiddels is die al ongeldig geworden.

Waarom geef je uberhaupt een array als parameter mee, als deze toch al globaal beschikbaar is (je 'ad4' variabele)?

Verwijderd

Uhmmm nogal logisch.

Met deze regel:

code:
1
setTimeout('chgAd('+ad+')',1000);


Gaat de boel de mist in. ad is namelijk een Array. Die Array kan je op die manier niet doorgeven. Zoals deheer boven mij al zegt: het is onnodig om de array als parameter mee te geven.

  • Johnny
  • Registratie: December 2001
  • Laatst online: 22-05 10:01

Johnny

ondergewaardeerde internetguru

Topicstarter
Omdat er ook nog een ad1, ad2 en ad3 bij komen die allemaal gebruik maken van dezelfde functies, daarom is het wel nodig om de array als parameter mee te geven.

Als ik de array naar een nieuwe, tijdelijke globale array kopieer om te voorkomen dat hij weer wordt verwijderd blijft het probleem bestaan.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • Xlnt
  • Registratie: Oktober 2000
  • Laatst online: 03-05 18:18
Johnny schreef op 12 juli 2004 @ 21:36:
Omdat er ook nog een ad1, ad2 en ad3 bij komen die allemaal gebruik maken van dezelfde functies, daarom is het wel nodig om de array als parameter mee te geven.
Dat werkt niet met setTimeout(code, timeout). Je kunt enkel een string code meegeven die wordt geëvalueerd na timeout seconden. Zodra je 'chgAd(' + ad + ')' als code opgeeft, wordt de string waarde van het array ad gebruikt. Dat is hetzelfde setTimeout('chgAd(ad4, aa, bb, cc, dd)', 1000) aanroepen. Ofwel na timeout seconden roept je chgAd vanuit globale scope aan met argumenten ad4, aa, bb, cc en dd. Toevallig bestaat er een globale variabele met de naam gelijk aan het eerste element van het array. Maar het gaat fout bij het tweede argument, aa, dat niet bestaat. Nergens, en zeker niet in globale scope.
Als ik de array naar een nieuwe, tijdelijke globale array kopieer om te voorkomen dat hij weer wordt verwijderd blijft het probleem bestaan.
Probeer een globaal array van arrays. Zoals het volgende.
code:
1
2
3
4
var ads = [];
ads["ad1"] = ["aa", "bb", cc", ...];
ads["ad2"] = ["dd", "ee", "ff", ...];
...

Je kunt dan de index, zoals "ad1", "ad2" enz., meegeven als string paramater aan de betreffende functies.

[ Voor 7% gewijzigd door Xlnt op 12-07-2004 23:58 ]

"It's not that I'm lazy. It's that I just don't care."


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Je kan je array ook omzetten naar een string-presentatie:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function foo() {

  a = [1,2,3,4];
  setTimeout('bar('+a.toSource()+')',1000);  // werkt alleen in browsers die JavaScript 1.3 ondersteunen
  setTimeout('bar(['+a.toString()+'])',2000);  // werkt ook in IE

}

function bar(b) {

  alert(b[1]);

}
foo();


Note dat toString problemen geeft als er strings in je array zitten; het beste is om voor IE ook een toSource() method te schrijven ;)

[ Voor 18% gewijzigd door crisp op 13-07-2004 07:43 ]

Intentionally left blank


  • Johnny
  • Registratie: December 2001
  • Laatst online: 22-05 10:01

Johnny

ondergewaardeerde internetguru

Topicstarter
Hoewel crisp normaal de JavaScript-man is heb ik toch de oplossing van Xlnt gebruikt, dat werkt, met een paar regeltjes code in alle browsers en gaat volgens mij een stuk sneller, wat niet onbelangrijk is omdat MSIE al loopt te hakkelen op de pagina waar het gebruikt gaat worden.

Wel moet ik er bij zeggen dat wanneer ik ads['ad1'] gebruikte het ook niet werkte, ads[1] werkte gelukkig wel, en die "ad" plak ik er gewoon later voor, dat scheelt ook meteen weer een paar bytes.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<html>
<head>
<title>Javascript test</title>
<script type="text/javascript">

var ads =  [];

ads[1] =['aa','bb','cc','dd'];
ads[2] =['aa','bb','cc','dd'];
ads[3] =['aa','bb','cc','dd'];
ads[4] =['aa','bb','cc','dd'];

function init(){
    chgAd(1);
    chgAd(2);
    chgAd(3);
    chgAd(4);
}

function chgAd(n){
    setAd(Math.round(Math.random()*(ads[n].length-1)),n);
}

function setAd(i,n){
    document.getElementById('ad'+n).innerHTML=ads[n][i];
    setTimeout('chgAd('+n+')',200);
}

</script>
</head>

<body onload="init();">

<div id="ad1"></div>
<div id="ad2"></div>
<div id="ad3"></div>
<div id="ad4"></div>

</body>
</html>

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

De methode met een global array is inderdaad sneller en in dit geval dus ook de betere oplossing, ik wou alleen maar aangeven hoe het mogelijk is om toch in een timeout een array door te geven ;)
Het probleem dat je geen ad1 kan doorgeven is ook simpel op te lossen:
JavaScript:
1
setTimeout('chgAd(\'ad'+n+'\')',200);

let op de escaped quotes ;)

Als je het nog sneller wilt hebben sla dan ook de referentie naar je objecten op in een array; dat scheelt je weer lookups.

[ Voor 16% gewijzigd door crisp op 13-07-2004 13:38 ]

Intentionally left blank

Pagina: 1