2016-11-27 2 views
3

Я строю игру симона. И после каждого раунда игрок должен увидеть ходы, которые он должен сыграть в следующем раунде. Поэтому я создал функцию showMoves, которая мигает квадрат, который он должен играть. Проблема в том, что функция ничего не показывает. Может ли кто-нибудь сказать мне, что я пропустил?не удалось установитьTimeout в цикле for

// the effect 
function flasher(index) { 
    $(moves[index]).fadeIn(50).fadeOut(50).fadeIn(50).fadeOut(50).fadeIn(100); 
} 
var interval2; 
// show the moves that supposed to be played 
function showMoves() { 
    for (var i = 0; i < moves; i++) { 
     if (i === 0) { 
      interval2 = setTimeout(flasher(i), 1000); 
     } else { 
      interval2 = setTimeout(flasher(i), (i+1) * 1000); 
     } 
    } 
} 
+1

вам должен пройти функцию reference.'setTimeout (function() {flasher (i);}, 1000); ' –

+1

@FastSnail, у вас все еще будет [эта ситуация] (http://stackoverflow.com/questions/1451009/ja vascript-infamous-loop-issue), переменная 'i' будет одинаковой во всех вызовах' flasher' –

+1

'1000 === (0 + 1) * 1000'; Помимо более крупной проблемы эти ветви избыточны. – Oka

ответ

1

setTimeout принимает функцию в качестве первого параметра. Я предполагаю, что, позвонив flasher, вы попытались избежать this situation. В вас случае, это должно быть сделано так:

function showMoves() { 
    for (var i = 0; i < moves; i++) { 
     if (i === 0) { 
     interval2 = setTimeout(function(i) {return function() {flasher(i)}}(i), 1000); 
     } else { 
     interval2 = setTimeout(function(i) {return function() {flasher(i)}}(i), (i+1) * 1000); 
     } 
    } 
    } 
0

SetTimeout и setInterval немного diffrent, чем мы думаем о них. Они сохраняют определенное событие в указанное время, которое будет запущено в свое время. Из-за этого они есть проблема с петлями:

for(i=0;i<3;i++) 
{ 
setTimeout(function(){alert(i)}, i*1000); 
} 

после окончания цикла браузер имеет 3 рабочие места, чтобы сделать:

alert(i) after 1 second 
alert(i) after 2 seconds 
alert(i) after 3 seconds 

Но что значение «я». Если вы находитесь в программировании C# после окончания цикла, то «i» будет удалено, и мы этого не сделаем. Но javascript не распоряжается «i», и мы его еще не видели. Таким образом, браузер задает текущее значение для i, которое равно 3., потому что, когда «i» достигает 3 циклов, заканчивается. Поэтому Ваш браузер делает это:

alert(3) after 1 second 
alert(3) after 2 seconds 
alert(3) after 3 seconds 

Это не то, что мы хотим. Но если изменить приведенный выше код для этого:

for(i=0;i<3;i++){ 
     (function (index) 
      { 
       setTimeout(function() { alert(index); }, i * 1000); 
      })(i); 
} 

Мы будем иметь:

alert(0) after 1 second 
alert(1) after 2 seconds 
alert(2) after 3 seconds 

Так как сказал Maximus вы тучными сделать браузер, чтобы получить значение я в настоящее время в цикле. таким образом:

setTimeout(function(i) {return function() {flasher(i)}}(i), (i+1) * 1000); 

Я не оставляю до конца цикла и должен получить значение только сейчас.

0

Что я могу извлечь из вашего кода, так это то, что moves - это массив, но вы используете его, как если бы он был целым числом в цикле for. И вот почему ничего не происходит.

Заменить:

for (var i = 0; i < moves; i++) { 

С:

for (var i = 0; i < moves.length; i++) { 

И вы должны видеть вещи происходит.

Но вы заметите, что flasher вызывается немедленно, без тайм-аута. И это потому, что вызывается результат flasher, а не flasher.
Другие ответы здесь предлагают использовать функцию обертки, но для этого требуются обходные пути, чтобы правильно передать индекс функции, вызванной setTimeout. Так при условии, что он не должен работать в IE8 и ниже перечисленного является наиболее кратким решением:

setTimeout(flasher.bind(null, i), (i+1) * 1000) 

Полный рабочий пример:

var moves = [1, 2, 3, 4]; 
 

 
function flasher(index) { 
 
    console.log('move', moves[index]); 
 
} 
 
var interval2; 
 
// show the moves that supposed to be played 
 
function showMoves() { 
 
    for (var i = 0; i < moves.length; i++) { 
 
     interval2 = setTimeout(flasher.bind(null, i), (i+1) * 1000); 
 
    } 
 
} 
 
    
 
showMoves()

Смежные вопросы