1

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

Оригинальный вопрос: У меня возникли проблемы с созданием таймера обратного отсчета 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, но это также дает тот же результат. Может ли кто-нибудь помочь? Я был бы очень признателен!

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

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

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

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

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

+0

Для справок в будущем, когда вопрос о моей порождает новый, я должен начать новую тему? – hora

ответ

2

отметить также, что

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

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

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

Итак, чтобы передать функцию Y.Lang.later, которая выполнила бы это 1000 мс позже, вместо возвращаемого значения функции? – hora

+0

yep.timer_trigger, как написано выше, не включает оператор return, поэтому по умолчанию он возвращает undefined. Для Y.Lang.later (1000, Y, timer_trigger()) undefined передается Y.Lang.later как функция, выполняемая за одну секунду. это переводится в setTimeout (function() {undefined.apply (Y);}, 1000); , который является ошибкой во время выполнения. – Luke

3

Проблема не состояние гонки. Причина, по которой дополнительный вызов 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, что позволяет блокировать еще будет выполняться.

+0

Вау, я в шоке, я пропустил это ... хотя мой timer_from никогда не доходил до 1, так как я всегда останавливал его около 200 или около того. Ответ Луки на самом деле объясняет, почему мой таймер-триггер не дождался 1000 мс для стрельбы. – hora