[JAVASCRIPT] Wat doet setTimeout hier nu eigenlijk?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
Soms krijg ik een idee en wil ik gelijk testen hoe het zou werken. Zo ook nu. Het is het duidelijkst als ik gewoon de code plaats en daarna kort toelicht.

JavaScript:
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
function runme(  )
{
    var func = arguments.callee;
    var callback;
    
    window.setTimeout( function(  )
    {
        // Normaal hier iets doen
        // Daarna checken of er een onComplete callback is en uitvoeren
        if( func.callback )
            func.callback(  );
    }, 0 );
    
    return {
        then: function( callback )
        {
            func.callback = callback;
        }
    };
}

// call runme, en chain een callback functie
runme().then( function(  )
{
    debug( 'here' );
} );


Nu, het gaat me niet om de functionaliteit; om te doen wat ik hier doe zijn er genoeg alternatieven. Wat me echter opvalt, is dat de debug 'here' bij mij ALTIJD geprint wordt, ook al staat de setTimeout op 0.

Dit betekent bij mij dat de code na de setTimeout altijd eerder wordt uitgevoerd dan de function call in de setTimeout, ook al staat er dat 'ie eigenlijk geen delay heeft. Zelf zou ik verwachten dat dit wat meer random zou zijn. De ene keer is de timeout sneller, de andere keer niet.

Mijn vraag nu dus: heeft iemand een idee hoe setTimeout zich nou gedraagd achter de schermen? Waarom runt het altijd later?

Hopelijk ben ik een beetje duidelijk :) Ben benieuwd!

Acties:
  • 0 Henk 'm!

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 14:20

DataGhost

iPL dev

Volgens mij komt het doordat Javascript eigenlijk maar met 1 thread werkt en niet aan interleaving doet. Op het moment dat jij setTimeout aanroept wordt de aan te roepen functie in een queue gezet en pas na het compleet uitvoeren van de huidige functie (call stack) wordt daarnaar gekeken. Aangezien je runme().then() doet wordt eerst runme() uitgevoerd en daarna then(), je 'hoofdfunctie' is immers nog niet klaar. Daarna pas is je 'thread' 'vrij' en kan naar de queue gekeken worden.

Acties:
  • 0 Henk 'm!

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
Oh dat is eigenlijk bijzonder interessant. Dat zou dus betekenent dat je eindeloos lang .then()'s kan chainen, en dat de timeout pas uitgevoerd wordt na de complete callstack van, bijv, runme().then().then().then().then();

Een soort van defer krijg je dan eigenlijk?

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:36

crisp

Devver

Pixelated

Ja, dat is inderdaad het gevolg van het single-threaded zijn. Overigens houden de meeste browsers een minimum timeout aan van ongeveer 10 milliseconden. 0 opgeven heeft dan sowieso geen ander effect.

edit: in HTML5 wordt gesproken van een minimum timeout waarde van 4ms voor setTimeout en 10ms voor setInterval:
If the currently running task is a task that was created by either the setTimeout() method, and timeout is less than 4, then increase timeout to 4.

[ Voor 45% gewijzigd door crisp op 29-09-2009 12:18 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
En Internet Explorer trekt de kar met een minimum van rond de 25 à 30 ms geloof ik.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Overigens is de code een beetje vaag. Je declareert een variabele 'callback', die je nergens gebruikt, en de daadwerkelijke callback zet je op 'func' die in feite gewoon naar 'runme' wijst. Ik weet niet of het de bedoeling is, maar het bugt zodra je meerdere keren achter elkaar runme().then() zou aanroepen omdat je de callback dan steeds overschrijft ipv dat je voor elke runme() context een nieuwe aanmaakt.

Bedoel je niet gewoon dit?
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function runme(  ) 
{ 
    var callback; 
     
    window.setTimeout( function(  ) 
    { 
        // Normaal hier iets doen 
        // Daarna checken of er een onComplete callback is en uitvoeren 
        if(callback) 
           callback(); 
    }, 0 ); 
     
    return { 
        then: function(c) 
        { 
            callback = c; 
        } 
    }; 
}

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Tjoekbezoer
  • Registratie: Maart 2003
  • Laatst online: 18-11-2024
Nee, je hebt gelijk .oisyn. Ik had het eerst anders aangepakt, en maar gedeeltelijk aangepast. Deze code was meer bedoeld als test, dus ik heb er verder niet heel veel aandacht aan besteed. De uiteindelijke implementatie wordt anders.

Maar, scherp :)
Pagina: 1