setTimeout in for-lus

Status
Niet open voor verdere reacties.

tazzzie007

Gebruiker
Lid geworden
28 nov 2009
Berichten
18
Goeiedag,

Voor een schoolwerk moeten we zorgen dat een aantal radiobuttons met een tijdverschil geselecteerd worden. Nu, als ik de code uittest wacht het script 2 seconden, maar toont dan alles in 1 keer.
Het is (vanzelfsprekend) niet de bedoeling dat jullie mijn schoolwerk doen, maar een zetje in de goede richting is wel welkom ;p

Het scriptje:
Code:
<script type="text/javascript">
  //<![CDATA[
    document.addEventListener('load',game1,false);
    var tijd;
    var i = 0;
    var j = 0;
    function game1() {	
	reeks1 = document.getElementById("reeks1");
	while(i < reeks1.childNodes.length) {
	    setTimeout("check()", 2000);
	    i++
	}
     }

    function check() {
	document.getElementById('reeks1').childNodes[j].checked = 'true';
	j++;
    }

  //]]>
</script>

HTML:
Code:
<div id="reeks1">
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
    <input type="radio" />
</div>

Alvast bedankt
Tazzzie007
 
Oké, dit is wat er gebeurt:
Op het moment dat het load-event voor document plaatsvindt, wordt je functie game1 uitgevoerd. De while-loop wordt uitgevoerd, het eerste statement daarvan is een aanroep van de functie setTimeout. In tegenstelling tot wat je lijkt te denken, wacht het script niet 2000 milliseconden alvorens verder te gaan. Het script (de while-loop) gaat gewoon verder, maar er wordt wel begonnen met aftellen: 2 seconden later wordt de functie check uitgevoerd voor iedere keer dat je het setTimeout-statement bent tegengekomen. Omdat je computer ongelofelijk snel die while-loop uitvoert, worden alle timers ogenschijnlijk tegelijk gezet, en worden 2 seconden later alle radio's (ogenschijnlijk) tegelijk geselecteerd.

Mogelijke aanpassingen:
(1) Zorg in de functie game1 dat de delay steeds iets wordt opgehoogd (bv. met 2 seconden). Alle timers worden dan direct gemaakt, maar het duurt dan 2000, 4000, 6000, ect. milliseconden voordat die timer check gaat uitvoeren.
[JS]var delay = 2000;
while(i < reeks1.children.length) { //Ik heb children gebruikt ipv childNodes. Zie voetnoot*
setTimeout("check()", delay);
i++;
delay += 2000;
}[/JS]
ofwel
[JS]while(i < reeks1.children.length) {
setTimeout("check()", 2000 * (i + 1));
i++;
}[/JS]

(2) Maak steeds aan het einde van check een nieuwe timer van 2 seconden voor de volgende radiobutton. Je moet dan wel een testje inbouwen om te zorgen dat er alléén een timer gemaakt wordt als je niet het laatste element te pakken hebt:
[JS]function check() {
var reeks1 = document.getElementById('reeks1');
reeks1.children[j].checked = 'true';
j++;
if (j < reeks1.children.length) {
//zet een nieuwe timer
}
}[/JS]

* children geeft een lijst van elementen in reeks1, childNodes geeft een lijst van zowel elementen als stukjes tekst (tekstNodes). Ter illustratie:
HTML:
<element id="element">
    <child></child>test 
    <child></child>
</element>
[JS]document.getElementById("element").children; //[<child>, <child>]
document.getElementById("element").childNodes; //["\n ", <child>, "test\n ", <child>, "\n"][/JS]
 
Als aanvulling:

setInterval en setTimeout hebben als eerste parameter een functie-referentie, niet een string. Het werkt wel, maar wat er dan intern gebeurt is dat de code geeval'd wordt; slecht plan. Helemaal nu je een functie zonder parameters hebt, kan je gewoon de naam erin gooien:

[JS] setTimeout(check, ...); // zonder (); je roept de functie niet aan, je refereert ernaar[/js]



:thumb:
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan