Почему мой цикл не ждет между итерациями? setTimeout()

#javascript #jquery #settimeout

Вопрос:

Я создаю игру «Саймон говорит» http://codepen.io/meek/pen/adrbOv используя jquery, и у меня возникли некоторые проблемы с воспроизведением каждого звука по одному.

Когда игра начинается, генерируется список из 20 звуков («ходов»), которые будут воспроизводиться один за другим каждый ход. Поэтому, если список ходов [ «красный», «желтый», «зеленый»], на первом ходу будет играть «красный», на втором — «красный» и «желтый» и так далее.

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

 turn = 4;
var t = 1;
  while(t <= turn) {
    setTimeout(AIbutton(allMoves[t-1]), 1000);
    t  ;
  }
 

AIbutton() это функция, которая воспроизводит звук (имитирует нажатие кнопки) и allMoves представляет собой список из 20 ходов, которые будут воспроизводиться на протяжении всей игры. Я хочу, чтобы это произошло, чтобы звук воспроизводился на каждой итерации цикла, прежде чем переходить к следующей итерации, но происходит то, что все звуки в цикле воспроизводятся одновременно после интервала в 1000 мс.

Я думал, что setTimeout сделает это так, чтобы он делал паузы между итерациями? Как я могу этого достичь?

Ответ №1:

setTimeout выполняется асинхронно, он не блокируется. Если вы хотите дождаться окончания тайм-аута, следующая «итерация цикла» должна произойти в обратном вызове функции, которую вы задаете setTimeout.

Что-то вроде этого сработало бы:

 turn = 4;
var t = 1;
ourTimeout(allMovies, turn, t);

function ourTimeout(allMovies, turn, t){
    AIbutton(allMoves[t-1]);
    if(t <= turn)
        setTimeout(ourTimeout(allMovies, turn,   t), 1000);
}
 

@Alnitak упоминает, что эта строка кода:

 setTimeout(ourTimeout(allMovies, turn,   t), 1000);`
 

необходимо изменить на это:

 setTimeout(function(){
        ourTimeout(allMovies, turn,   t);
    }, 1000);
 

Как утверждает @Alnitak, вы можете передать в setTimeout только анонимную или именованную функцию. Трюк с передачей переменных выполняется так, как указано выше (концепция называется закрытием).

Комментарии:

1. этот код неверен — вам нужно передать ссылку на функцию setTimeout (например, анонимное выражение функции), а не результат вызова ourTimeout .

2. Это делает именно то, что мне нужно, и теперь я понимаю, почему. Спасибо!