Pergunta

EDIT: Eu descobri a resposta para a pergunta original do YUI3 que publiquei aqui, mas levou a outra e, em vez de iniciar um novo tópico, pensei em adicioná -lo aqui. Por favor, role para baixo para a nova pergunta (está em negrito).

Pergunta original: Estou tendo alguns problemas para criar um cronômetro de contagem regressiva JavaScript dentro de uma definição de Yui, meu palpite é algo a ver com o escopo de objeto. Aqui está o meu 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);
    }


});

O erro que estou recebendo é que ele não espera os 1000ms como se estivesse pedindo para ligar timer_trigger() E o Safari finalmente me pergunta se eu quero parar de executar o código. Quando faço alguns segundos após o carregamento da página, o timer já caiu para cerca de 3, 4 minutos. Eu também tentei usar setTimeout Mas isso também produz o mesmo resultado. Alguém pode ajudar? Eu realmente apreciaria isto!

EDIT: Na verdade, descobri uma solução - isso veio depois de horas tentando toneladas de coisas, mas mais algumas pesquisas no Google às vezes ainda podem produzir novos resultados/respostas (encontrei a resposta em esse site, na realidade).

Então, aparentemente, meu código estava criando uma condição de corrida, e tudo o que eu precisava fazer para consertar é o seguinte:

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

Procurei condições de corrida, mas não está claro para mim o que isso significa no meu caso e como a mudança aparentemente trivial no meu código corrigiu o problema que eu estava tendo. Então, a pergunta original respondeu, mas eu gostaria de transformar isso na pergunta que surgiu da resposta.

Como funciona o encadeamento no JavaScript e o que causa minha condição de corrida e por que a menor mudança no código corrigiu o erro que eu tive?

Foi útil?

Solução

Observe também isso

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

Executa Timer_trigger imediatamente e passa o valor de retorno para y.lang.later. Você provavelmente quis dizer

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

Outras dicas

O problema não é uma condição de corrida. A razão pela qual a chamada adicional para o Settimeout "FILES" seu código é por causa de uma falha lógica em timer_trigger. Considere o que acontece no caso onde timer_from é 1 quando a função é chamada. Nem o timer: para baixo nem o timer: o final será acionado.

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

Você adicionou este código:

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

Isso causa timer_trigger ser chamado mais uma vez com timer_from já está definido como 0, permitindo que o bloco elimine seja executado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top