1

EDIT: J'ai trouvé la réponse à la question initiale YUI3 que j'ai posté ici, mais elle a conduit à une autre et au lieu de commencer un nouveau fil, je pensais que je voudrais juste l'ajouter ici. S'il vous plaît faites défiler vers le bas pour la nouvelle question (il est en caractères gras).Javascript course condition question

Question d'origine: Je rencontre des problèmes lors de la création d'un compte à rebours JavaScript à l'intérieur d'une définition YUI, je suppose que cela concerne la portée des objets. Voici mon code:

YUI({combine: true, timeout: 10000}).use("node", function (Y) { 
    var timer = new function(){}; 
    Y.augment(timer, Y.EventTarget); 
    timer.on('timer:down', function() { 
     Y.log('timer down event fired', 'event'); 
     Y.Lang.later(1000, Y, timer_trigger()); 
    }); 
    timer.on('timer:end', function() { 
     Y.log('timer end event fired', 'event'); 
    }); 

    var timer_from; 

    function startTimer(seconds){ // start a coundown from seconds to 0 
     timer_from = seconds; 
     timer_trigger(); 
    } 

    function timer_display(){ 
     var mins = Math.floor(timer_from/60); 
     var secs = timer_from - mins*60; 
     var secsDisp = secs; 
     if(secs<10){ 
      secsDisp = '0' + secs; 
     } 
     Y.one('#timer').set('innerHTML', mins + ':' + secsDisp); 
    } 

    function timer_trigger(){ 
     Y.log('timer from is: '+timer_from); 
     if(timer_from > 0){ 
      timer_from--; 
      timer_display(); 
      if(timer_from > 0){ 
       timer.fire('timer:down'); 
      } 
     } else { 
      timer.fire('timer:end'); 
     } 
    } 

    function initializePage(){ 
     startTimer(900); 
    } 


}); 

L'erreur que je reçois est qu'il n'attend pas les 1000ms comme que je demande à appeler timer_trigger() et Safari me demande finalement si je veux arrêter l'exécution du code. Quand je fais quelques secondes après le chargement de la page, la minuterie est déjà à environ 3, 4 minutes. J'ai également essayé d'utiliser setTimeout mais cela produit également le même résultat. Quelqu'un peut-il aider? J'apprécierai vraiment cela!

EDIT: En fait, je compris une solution - cela est venu après les heures d'essayer des tonnes de choses, mais quelques autres recherches Google peut parfois produire encore de nouveaux résultats/réponses (j'ai trouvé la réponse sur this site, en fait).

Donc, apparemment, mon code a été crée une condition de course, et tout ce que je devais faire pour y remédier est la suivante:

setTimeout(function(){ 
    timer_trigger(); 
}, 1000); 

J'ai regardé les conditions de course, mais il est clair pour moi ce que cela signifie dans mon cas et comment le changement apparemment insignifiant de mon code a résolu le problème que j'avais. Donc, la question initiale a été répondue, mais j'aimerais en faire la question qui découle de la réponse.

Comment le threading dans JavaScript fonctionne-t-il et quelles sont les causes de mes conditions de concurrence, et pourquoi le mineur a-t-il corrigé l'erreur que j'avais?

+0

Pour référence future, quand une question de la mienne engendre un nouveau dois-je commencer un nouveau fil? – hora

Répondre

2

Notez également que

Y.Lang.later(1000, Y, timer_trigger()); 

exécute immédiatement et timer_trigger passe la valeur de retour à Y.Lang.later. Vous avez probablement voulu dire

Y.Lang.later(1000, Y, timer_trigger); 
+0

Alors que passerait la fonction à Y.Lang.later, qui l'exécuterait 1000ms plus tard, au lieu de la valeur de retour de la fonction? – hora

+0

oui.timer_trigger tel qu'il est écrit ci-dessus n'inclut pas d'instruction return, donc par défaut il renvoie undefined. Pour Y.Lang.later (1000, Y, timer_trigger()), undefined est passé à Y.Lang.later en tant que fonction à exécuter en une seconde. cela se traduit par setTimeout (function() {undefined.apply (Y);}, 1000); qui est une erreur d'exécution. – Luke

3

Le problème n'est pas une condition de concurrence. La raison pour laquelle l'appel supplémentaire à setTimeout "corrige" votre code est due à un défaut logique dans timer_trigger. Considérez ce qui se passe dans le cas où timer_from est 1 lorsque la fonction est appelée. Aucune minuterie: en bas et en minuterie: la fin sera déclenchée.

function timer_trigger(){ 
    Y.log('timer from is: '+timer_from); 
    if(timer_from > 0){  // Since timer_from is 1, the if block is entered 
     timer_from--;  // timer_from is 0 
     timer_display(); 
     if(timer_from > 0){ // This block is not entered, but it has no matching else 
      timer.fire('timer:down'); 
     } 
    } else {     // The matching if block was entered, so this is not 
     timer.fire('timer:end'); 
    } 
} 

vous avez ajouté ce code:

setTimeout(function(){ 
    timer_trigger(); 
}, 1000); 

Cela provoque timer_trigger d'être appelé une fois de plus avec timer_from déjà mis à 0, ce qui permet au bloc d'autre à exécuter.

+0

Wow, je suis choqué que j'ai manqué cela ... bien que mon timer_from ne soit jamais arrivé à 1, puisque je l'ai toujours arrêté environ 200 ou plus. La réponse de Luke explique en fait pourquoi mon timer_trigger n'a pas attendu 1000ms pour tirer. – hora

Questions connexes