Pregunta

EDIT: me di cuenta de la respuesta a la pregunta original YUI3 he publicado aquí, pero es llevado a otro y en lugar de iniciar un nuevo hilo pensé que acababa de añadir aquí. Por favor, desplácese hacia abajo para la nueva pregunta (que está en negrita).

pregunta original: Estoy teniendo algunos problemas que crean un temporizador de cuenta atrás JavaScript dentro de una definición de YUI, yo creo que es algo que ver con la determinación del alcance del objeto. Aquí está mi código:

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);
    }


});

El error que estoy recibiendo es que no espera a los 1000 ms como si estuviera pidiéndole que llame a timer_trigger() y Safari finalmente me pregunta si quiero detener la ejecución del código. Cuando hago un par de segundos después de cargar la página, el temporizador ya está abajo a cerca de 3, 4 minutos. También he intentado usar setTimeout sino que también produce el mismo resultado. ¿Alguien puede ayudar? Yo lo agradecería muchísimo!

EDIT: De hecho, me di cuenta de una solución - esto se produjo después de horas de intentar un montón de cosas, pero un poco más de búsquedas de Google pueden a veces todavía producir nuevos resultados / respuestas (que encontré la respuesta en este sitio , en realidad).

Así que al parecer mi código estaba creando una condición de carrera, y todo lo que tenía que hacer para solucionarlo es la siguiente:

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

Miré las condiciones de carrera, pero no está claro para mí lo que significa en mi caso, y cómo el cambio aparentemente trivial para mi código ha solucionado el problema que estaba teniendo. Así que la pregunta original en respondió, pero me gustaría convertir esto en la pregunta que surge de la respuesta.

¿Cómo funciona el hilo en el trabajo y lo que JavaScript causar mi condición de carrera, y por qué el pequeño cambio en el código de corregir el error que tuve?

¿Fue útil?

Solución

También tenga en cuenta que

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

ejecuta timer_trigger inmediatamente y pasa el valor de retorno para Y.Lang.later. Probablemente quería decir

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

Otros consejos

El problema no es una condición de carrera. La razón por la llamada adicional a setTimeout "fija" el código es debido a una falla en la lógica timer_trigger. Considere lo que sucede en el caso de que timer_from es 1 cuando la función es llamada. Ni temporizador: abajo ni temporizador:. Extremo se activará

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');
    }
}

Añadiste este código:

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

Esto provoca timer_trigger a ser llamado una vez más con timer_from ya se pone a 0, lo que permite el bloque más para ser ejecutado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top