Вопрос

Редактировать:Я выяснил ответ на оригинальный вопрос YUI3, который я разместил здесь, но это привело к другому вопросу, и вместо того, чтобы начинать новую тему, я подумал, что просто добавлю его сюда.Пожалуйста, прокрутите страницу вниз, чтобы найти новый вопрос (он выделен жирным шрифтом).

Оригинальный вопрос:У меня возникли некоторые проблемы с созданием таймера обратного отсчета JavaScript внутри определения YUI, я предполагаю, что это как-то связано с определением области видимости объекта.Вот мой код:

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


});

Ошибка, которую я получаю, заключается в том, что он не ожидает 1000 мс, как я прошу его вызвать timer_trigger() и Safari в конце концов спрашивает меня, хочу ли я прекратить выполнение кода.Когда я делаю это через несколько секунд после загрузки страницы, таймер уже снизился примерно до 3-4 минут.Я также пробовал использовать setTimeout но это также приводит к тому же результату.Кто-нибудь может помочь?Я был бы действительно признателен вам за это!

Редактировать:Я действительно нашел решение - это появилось после нескольких часов попыток множества вещей, но еще несколько поисковых запросов Google иногда все еще могут давать новые результаты / ответы (я нашел ответ на этот сайт, на самом деле).

Итак, очевидно, что мой код создавал состояние гонки, и все, что мне нужно было сделать, чтобы исправить это, это:

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

Я посмотрел условия гонки, но мне неясно, что это означает в моем случае, и как, казалось бы, тривиальное изменение в моем коде устранило проблему, с которой я столкнулся.Итак, на первоначальный вопрос дан ответ, но я хотел бы превратить это в вопрос, который возник из ответа.

Как работает потоковая передача в JavaScript и что вызывает мое состояние гонки, и почему незначительное изменение в коде исправило мою ошибку?

Это было полезно?

Решение

Также обратите внимание , что

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

немедленно выполняет timer_trigger и передает возвращаемое значение Y.Lang.later.Вы, вероятно, имели в виду

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

Другие советы

Проблема не в состоянии гонки.Причина, по которой дополнительный вызов setTimeout "исправляет" ваш код, заключается в логическом недостатке в timer_trigger.Рассмотрим, что происходит в случае, когда timer_from равно 1 при вызове функции.Ни таймер: выключение, ни таймер: завершение не будут запущены.

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

Вы добавили этот код:

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

Это вызывает timer_trigger быть вызванным еще раз с timer_from уже установлено значение 0, позволяющее выполнить блок else.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top