Линия в цикле не выполняется

0
var games = [];
var numbers_to_letters = ["one", "two", "three", "four", "five", "six"]

function Game(){
    roll_animation();
}

$("#roll_dice").click(function(){
    games.push(new Game());
});

function roll_animation(){
    for (var i = 0; i < 100; i++){
        for (var j = 0; j < 5; j++){
            (function(ind){
                window.setTimeout(function(){
                    $(".btn.btn-die").addClass(numbers_to_letters[ind+1]).removeClass(numbers_to_letters[ind]);
                }, 20 * (ind + 1));
            })(j);
        }
        $(".btn.btn-die").addClass("one").removeClass("six");
    }
}

Последняя строка в первом цикле не выполняется, если я не нажму кнопку еще раз, в результате чего второй цикл будет выполняться только один раз. (требуется перезагрузка, чтобы снова работать). Почему последняя строка не выполняется?

  • 1
    setTimeout не блокируется, поэтому последняя строка будет выполняться все 100 раз до запуска первого кода setTimeout .
  • 0
    ... также все ваши вызовы setTimeout будут выполняться примерно в одно и то же время, но со смещением в 20 мс.
Показать ещё 2 комментария
Теги:

1 ответ

1
Лучший ответ

По-видимому, это проблема асинхронного кода в функции setTimeout() запущенная через некоторое время и, таким образом, не синхронизирована с другим кодом в циклах.

Строка кода, о которой идет речь:

$(".btn.btn-die").addClass("one").removeClass("six");

работает просто отлично. Но поскольку вызовы setTimeout() запланированы для выполнения некоторого таймера LATER, все они запускаются после выполнения этой выше строки. Таким образом, эта строка кода запускается, а затем таймеры setTimeout() запускают стрельбу, и эффект вышеприведенной строки перезаписывается. Это то, что ваш код дал ему указание.

Если вы замедляете время, вы можете увидеть, что здесь происходит в этой демонстрации вашего треда: http://jsfiddle.net/jfriend00/tqYq7/

Если вы хотите, чтобы указанная выше строка кода запускалась ПОСЛЕ последнего срабатывания таймера, вам нужно написать свой код, чтобы сделать это, а не так, как вы его сейчас написали. Мне непонятно, что вы пытаетесь сделать с этой строкой кода, так что я точно не знаю, что рекомендовать.

Можно спросить, почему вы устанавливаете 500 таймеров, большинство из которых собираются уйти в одно и то же время и запустить тот же самый код? Есть, конечно, более эффективные способы запуска чего-то повторяющимся образом. Если то, что вы действительно пытаетесь сделать, - это запустить внутреннюю анимацию 100 раз, один за другим, тогда вам придется кодировать совершенно по-другому, потому что то, что вы сейчас делаете, - это установка 100 копий тех же таймеров, которые все запланированы в то же время.

Здесь демо для другого способа программирования, у которого нет проблем, которые у вас есть.

Рабочая демонстрация: http://jsfiddle.net/jfriend00/Zsa8m/

var games = [];
var numbers_to_letters = ["one", "two", "three", "four", "five", "six"];

function Game(){
    roll_animation();
}

$("#roll_dice").click(function(){
    games.push(new Game());
});

function roll_animation(){
    var cntr = 0;

    function next() {
        var die = cntr % 6;
        var nextDie = (die + 1) % 6;
        $(".btn.btn-die")
            .addClass(numbers_to_letters[nextDie])
            .removeClass(numbers_to_letters[die]);
        ++cntr;
        // keep going as long as cntr < 100 and we aren't on number 1
        // so that the die always end on 1
        if (cntr < 100 || nextDie != 0) {
            setTimeout(next, 50);
        }
    }
    next();
}

Вы можете, очевидно, изменить константы в соответствии с вашими целями.

Просто для усмешек, здесь версия, которая катит случайно, а не последовательно: http://jsfiddle.net/jfriend00/NSW8U/

  • 0
    Внутренний цикл for предполагает изменение класса с одного на шесть, а последняя строка для сброса класса обратно на единицу, чтобы внутренний цикл мог повториться снова. Это для эффекта анимации.
  • 1
    @ user3348360 - выполняется последняя строка кода ДО запуска любого из ваших таймеров. Вы понимаете, что код таймера запускается когда-нибудь в будущем? Последняя строка кода запускается прямо перед таймерами. И ваш внешний цикл сейчас ничего не делает. Вам придется написать это, если вы хотите повторить анимацию 100 раз.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню