Как заставить jQuery дождаться завершения эффекта?

107

Я уверен, что читал об этом на днях, но нигде не могу найти.
У меня есть fadeOut()событие, после которого я удаляю элемент, но jQuery удаляет элемент до того, как у него появится возможность исчезнуть.
Как заставить jQuery ждать, пока элемент не исчезнет, ​​а затем удалить его?

уридий
источник

Ответы:

167

Вы можете указать функцию обратного вызова:

$(selector).fadeOut('slow', function() {
    // will be called when the element finishes fading out
    // if selector matches multiple elements it will be called once for each
});

Документация здесь .

Паоло Бергантино
источник
Бинго. Я думал, что это так, но мне нужно было поместить туда всю мою функцию, а не только часть удаления. PS Если кого-то интересует книга, которую я читал и теперь снова нашел, это «Изучение JQuery - лучшее взаимодействие и дизайн».
Еще
Если у кого-то есть старый jQuery, то эта ошибка "анимация завершена обратным вызовом" была неприятной: bugs.jquery.com/ticket/5684
JustAMartin
178

В версии jQuery 1.6 вы можете использовать этот .promise()метод.

$(selector).fadeOut('slow');
$(selector).promise().done(function(){
    // will be called when all the animations on the queue finish
});
Рейнальдо Младший
источник
4
Это является излишним для большинства JQuery анимации , как есть обратный вызов арг на большинстве методов, но с использованием promise()или when()и done()вы можете использовать некоторые очень прохладное поведение от методов 3 - й партии, или даже самостоятельно. +1 за значимость .promise()!
Стюарт
4
Не слышал этого раньше, просто спас мою задницу.
prismspecs
1
в моем случае я пытался получить доступ к текущей анимации элемента, который происходил где-то еще в моем коде, и поэтому у меня не было доступа к его обратному вызову. +1
Кристиан
11
Использование обещания () также позволяет вам настроить один обратный вызов, когда все будет сделано. Если вы вызываете fadeOut () для набора из 10 вещей, будет один обратный вызов для каждой вещи с 'this', установленным в соответствующей области. Если вы хотите выстрелить только один раз, эта функция действительно поможет. Также: если вы анимируете селектор, который соответствует нулю элементов, нормальный обратный вызов никогда не сработает. Promise () сработает в конце, несмотря ни на что.
zslayton
6
Вы также можете связать его так:$(selector).fadeOut('slow').promise().done(function(){...});
Syclone
9

Вы также можете использовать, $.when()чтобы дождаться promiseзавершения:

var myEvent = function() {
    $( selector ).fadeOut( 'fast' );
};
$.when( myEvent() ).done( function() {
    console.log( 'Task finished.' );
} );

Если вы выполняете запрос, который тоже может завершиться ошибкой, вы можете пойти еще дальше:

$.when( myEvent() )
    .done( function( d ) {
        console.log( d, 'Task done.' );
    } )
    .fail( function( err ) {
        console.log( err, 'Task failed.' );
    } )
    // Runs always
    .then( function( data, textStatus, jqXHR ) {
        console.log( jqXHR.status, textStatus, 'Status 200/"OK"?' );
    } );
кайзер
источник
2
Эта часть этого ответа с использованием $.when()не работает, потому myEvent()что не возвращает обещание и $.when()ожидает, что вы передадите ему одно или несколько обещаний, чтобы он выполнил свою работу.
jfriend00 08
6

если это что-то, что вы хотите переключить, затухая одно и затухая другое в одном месте, вы можете разместить атрибут {position: absolute} в div, чтобы обе анимации воспроизводились друг над другом, и у вас не было чтобы дождаться окончания одной анимации перед запуском следующей.

Samin
источник