Отложено на результат 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'); }); потому что обратный вызов будет происходить для КАЖДОГО анимированного элемента, в то время как обещания заключаются в том, что это была "задача" со многими подзадачами

http://jsfiddle.net/LbHrQ/3/

Лучше всего использовать обещания, когда вы хотите синхронизировать некоторые асинхронные операции по своей природе, такие как анимация, ajax, вещи, которые используют тайм-ауты (в этом случае вам нужно resolve() ваш отложенный вручную)

Другие вопросы по тегам