Отложено на результат jQuery.each
Я учу отсрочку, и не могу понять, как / почему это работает:
<html>
<head>
</head>
<body>
<div>
1</div>
<div>
2</div>
<div>
3</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$("div").each(function (i) {
$(this).delay(1000 * i).fadeOut();
}).promise().done(function () { console.log("it's done"); });
</script>
</body>
</html>
В практическом: почему я могу назвать обещание после каждого? Почему это технически возможно? Я console.logged:
console.log($("div").each(function (i) {}));
и я вижу метод обещания в прототипе. Но каждая моя функция не возвращает никаких значений, просто есть:
$(this).delay(1000 * i).fadeOut();
Так как же обещание связано с результатом анимации? (в основном результат каждой итерации)
РЕДАКТИРОВАТЬ 1: Просто чтобы прояснить, возможно, я должен был написать мой вопрос так:
Как это делается, метод done вызывается после завершения всех анимаций == как обещание связано с анимацией, которая выполняется внутри каждой функции обратного вызова.
2 ответа
Вы пытались добавить promise()
метод внутри блока? На данный момент вы выполняете его только после того, как вся итерация завершена.
$("div").each(function (i) {
$(this).delay(1000 * i).fadeOut().promise().done(function () { console.log("This individual animation is done."); });
}).promise().done(function () { console.log("Everything is done."); });
Ваш селектор div
на самом деле относится к довольно многим элементам на вашей странице. Поскольку он проходит через все, он выполняет определенное действие для этого элемента.
Затем вы просите jQuery выполнить другое действие, когда все предыдущие действия, связанные с этими элементами, завершены. Согласно их документации, он возвращает объект:
когда все действия определенного типа, связанные с коллекцией, в очереди или нет, завершены.
Итак, после каждого fadeOut()
выполнил в коллекции, console.log()
активирован
Я никогда не видел each
используется с обещаниями, но только с анимацией
$('div')
.animate({opacity: 0}, 1500) // animate all divs at once
.promise()
.done(function(){
console.log('all done');
});
это оживит все элементы div одновременно, а затем выполнит обратный вызов, когда все элементы div завершат анимацию. проблема с анимацией внутри цикла состоит в том, что она не может быть скоординирована, и вы не сможете контролировать, когда все они закончатся, если вы не используете обещания. Если вы действительно хотите использовать each
, вам придется сделать массив promises
затем используйте then
var promises = [];
$('div').each(function(){
var $this = $(this);
promises.push($this.fadeOut('slow').promise());
});
$.when.apply($, promises).then(function(){
console.log('all done');
});
Это не то же самое, что делать $('div').fadeOut('slow', function(){ alert('done'); });
потому что обратный вызов будет происходить для КАЖДОГО анимированного элемента, в то время как обещания заключаются в том, что это была "задача" со многими подзадачами
Лучше всего использовать обещания, когда вы хотите синхронизировать некоторые асинхронные операции по своей природе, такие как анимация, ajax, вещи, которые используют тайм-ауты (в этом случае вам нужно resolve()
ваш отложенный вручную)