Jak sprawić, by jQuery czekało, aż efekt zostanie zakończony?

107

Jestem pewien, że czytałem o tym kiedyś, ale nie mogę go nigdzie znaleźć.
Mam fadeOut()zdarzenie, po którym usuwam element, ale jQuery usuwa element, zanim będzie miał szansę zakończyć zanikanie.
Jak sprawić, by jQuery czekało, aż element wyblaknie, a następnie go usunie?

uriDium
źródło

Odpowiedzi:

167

Możesz określić funkcję zwrotną:

$(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
});

Dokumentacja tutaj .

Paolo Bergantino
źródło
Bingo. Myślałem, że tak, ale to, co musiałem zrobić, to umieścić całą moją funkcję, a nie tylko część do usunięcia. PS Jeśli ktoś jest zainteresowany książką, w której ją przeczytałem, a teraz znowu znalazłem, jest Learning JQuery - Better Interaction and Design.
Jeszcze
Jeśli ktoś ma stare jQuery, to ten błąd „animacja zakończona oddzwonieniem” był paskudny: bugs.jquery.com/ticket/5684
JustAMartin
178

W wersji jQuery 1.6 możesz skorzystać z .promise()metody.

$(selector).fadeOut('slow');
$(selector).promise().done(function(){
    // will be called when all the animations on the queue finish
});
Reinaldo Junior
źródło
4
Jest to zbędne dla większości animacji jQuery, ponieważ istnieją argumenty wywołania zwrotnego na większości metod, ale przy użyciu promise()lub when()i done()można wykorzystać niektóre bardzo fajne zachowanie od 3 metod partyjnych, a nawet własne. +1 za intencje .promise()!
stuartc,
4
Nie słyszałem tego wcześniej, po prostu uratowałem mój tyłek.
prismspecs
1
w moim przypadku próbowałem uzyskać dostęp do bieżącej animacji elementu, który dzieje się w innym miejscu w moim kodzie, przez co nie miałem dostępu do jego wywołania zwrotnego. +1
Kristian
11
Użycie promise () pozwala również na skonfigurowanie pojedynczego wywołania zwrotnego, gdy wszystko jest zrobione. Jeśli wywołasz fadeOut () na zestawie 10 rzeczy, nastąpi jedno wywołanie zwrotne dla każdej rzeczy z wartością „this” ustawioną na odpowiedni zakres. Jeśli chcesz odpalić tylko raz, ta funkcja jest naprawdę pomocna. Ponadto: jeśli animujesz na selektorze, który okazuje się pasować do zero elementów, normalne wywołanie zwrotne nigdy nie zostanie uruchomione. Promise () uruchomi się na końcu bez względu na wszystko.
zslayton
6
Możesz również połączyć to w następujący sposób:$(selector).fadeOut('slow').promise().done(function(){...});
Syclone
9

Możesz równie dobrze $.when()poczekać, aż promiseskończysz:

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

Jeśli wykonujesz żądanie, które równie dobrze może się nie powieść, możesz nawet pójść o krok dalej:

$.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"?' );
    } );
kajzer
źródło
2
Ta część odpowiedzi $.when()nie działa, ponieważ myEvent()nie zwraca obietnicy i $.when()oczekuje, że przekażesz jej jedną lub więcej obietnic, aby wykonała swoją pracę.
jfriend00
6

jeśli jest to coś, co chcesz zmienić, wyciszając jedną i wygaszając drugą w tym samym miejscu, możesz umieścić atrybut {position: Absolut} na elementach div, aby obie animacje były odtwarzane jedna na drugiej i nie masz poczekać na zakończenie jednej animacji przed uruchomieniem następnej.

Samin
źródło