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");
}
}
Последняя строка в первом цикле не выполняется, если я не нажму кнопку еще раз, в результате чего второй цикл будет выполняться только один раз. (требуется перезагрузка, чтобы снова работать). Почему последняя строка не выполняется?
По-видимому, это проблема асинхронного кода в функции 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/
setTimeout
не блокируется, поэтому последняя строка будет выполняться все 100 раз до запуска первого кодаsetTimeout
.setTimeout
будут выполняться примерно в одно и то же время, но со смещением в 20 мс.