Как написать цикл в jQuery, который ожидает завершения каждой функции, прежде чем продолжить цикл - PullRequest
12 голосов
/ 03 марта 2010

Пожалуйста, прости меня, если это очевидно.

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

Я попытался сделать это в цикле $ .each, но он быстро запустил команды и завершил их, не дожидаясь их завершения.

Есть идеи?

$('elem').each(function(){
    $(this).fadeIn().wait(5000).fadeOut();
});

Это то, что у меня есть, очень просто. Я получил функцию wait () отсюда: Сайт поваренной книги jquery .

Проблема в том, что цикл не ждет - фактическая команда работает, как задумано, просто они все сразу срабатывают.

Любая помощь приветствуется, спасибо.

РЕДАКТИРОВАТЬ: После того, как это будет выполнено, я, возможно, захочу снова выполнить цикл, так что список элементов будет снова исчезать / появляться в последовательности

EDIT2: С тех пор я получил jQuery lib 1.4.2, использовал 1.3.2, следовательно, пользовательскую функцию wait (). Теперь с помощью delay (), как упомянуто в lobstrosity. Удалось собрать воедино что-то близкое к тому, что мне нужно из его ответа, спасибо лобстросити :).

Ответы [ 4 ]

9 голосов
/ 03 марта 2010

Прежде всего, в jQuery 1.4 добавлена ​​функция delay , что, как я полагаю, и делает ваша пользовательская реализация ожидания.

Используя задержку, вы можете сортировать подделку функциональности каждого элемента, «ожидающего» предыдущего элемента, чтобы завершить работу, используя первый параметр для каждого обратного вызова в качестве множителя для начальной задержки. Как это:

var duration = 5000;

$('elem').each(function(n) {
    $(this).delay(n * duration).fadeIn().delay(duration).fadeOut();
});

Таким образом, первый элемент немедленно исчезнет. Вторая исчезнет через 5000 мс. Третий после 10000 мс и тд. Имейте в виду, что это притворяется. Каждый элемент не ожидает завершения предыдущего элемента.

3 голосов
/ 03 марта 2010

Ваш основной цикл, использующий each(), будет работать без задержки над вашей коллекцией элементов. Вместо этого вам нужно поставить в очередь эти элементы.

Для этого может потребоваться настройка (и возможно использование очередей jQuery?), Но для демонстрации использования рекурсии для обработки очереди:

function animate(elems) {
    var elem = elems.shift();
    $(elem).fadeIn().wait(5000).fadeOut(2000, function() {
        if (elems.length) {
            animate(elems);
        }
    });
}

var elems = $('elem');
animate(elems);
0 голосов
/ 03 марта 2010

Вот демонстрация моего решения .

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

// Create a function that does the chaining.
function fadeNext(x,y) {
  return function() { x.fadeIn(100).delay(100).fadeOut(1000, (y?y.fadeNext:y)); };
}

// Get all the elements to fade in reverse order.
var elements = [];
$('.f').each(function(i,e) {elements.unshift(e);});

// Iterate over the elements and configure a fadeNext for each.
var next;
for (var i in elements) {
  var e = $(elements[i]);
  e.fadeNext = fadeNext(e,next);
  next = e;
}

// Start the fade.
next.fadeNext();
0 голосов
/ 03 марта 2010

Вам, вероятно, нужно вызвать wait перед первой функцией:

  $(this).wait().fadeIn().wait(5000).fadeOut();

Другой вариант - использовать обратный вызов.

 $(this).wait().fadeIn('slow', function(){$(this).fadeOut('slow')});

Таким образом, fadeOut не запускается, пока не завершится fadeIn.

...