Comment faire attendre jQuery jusqu'à ce qu'un effet soit terminé?

107

Je suis sûr que j'ai lu à ce sujet l'autre jour, mais je n'arrive pas à le trouver nulle part.
J'ai un fadeOut()événement après lequel je supprime l'élément, mais jQuery supprime l'élément avant qu'il ait la chance de finir de disparaître.
Comment faire pour que jQuery attende que l'élément disparaisse, puis le supprimer?

uriDium
la source

Réponses:

167

Vous pouvez spécifier une fonction de rappel:

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

Documentation ici .

Paolo Bergantino
la source
Bingo. Je pensais que c'était ça, mais ce que je devais faire était d'y mettre toute ma fonction, pas seulement la partie de suppression. PS Si quelqu'un est intéressé par le livre dans lequel je l'ai lu et que j'ai maintenant retrouvé, c'est Learning JQuery - Better Interaction and Design. Merci encore
uriDium
Si quelqu'un a un ancien jQuery, alors ce bogue "animation effectuée par rappel" était méchant: bugs.jquery.com/ticket/5684
JustAMartin
178

Avec la version jQuery 1.6, vous pouvez utiliser la .promise()méthode.

$(selector).fadeOut('slow');
$(selector).promise().done(function(){
    // will be called when all the animations on the queue finish
});
Reinaldo Junior
la source
4
Ceci est redondant pour la plupart des animations jQuery car il existe des arguments de rappel sur la plupart des méthodes, mais en utilisant promise()ou when()et done()vous pouvez tirer parti d'un comportement très cool de méthodes tierces, ou même du vôtre. +1 pour signifier .promise()!
stuartc
4
Je n'ai pas entendu ça avant, j'ai juste sauvé mes fesses.
prismspecs
1
dans mon cas, j'essayais d'accéder à l'animation actuelle d'un élément qui se passait ailleurs dans mon code, et donc je n'avais pas accès à son rappel. +1
Kristian
11
L'utilisation de promise () vous permet également de configurer un seul rappel lorsque tout est terminé. Si vous appelez fadeOut () sur un ensemble de 10 choses, il y aura un rappel pour chaque chose avec «this» défini sur la portée appropriée. Si vous ne voulez tirer qu'une seule fois, cette fonction est vraiment utile. Aussi: Si vous animez sur un sélecteur qui s'avère correspondre à zéro élément, le rappel normal ne se déclenchera jamais. Promise () se déclenchera à la fin quoi qu'il arrive.
zslayton
6
Vous pouvez également l'enchaîner comme ceci:$(selector).fadeOut('slow').promise().done(function(){...});
Syclone
9

Vous pouvez également utiliser $.when()pour attendre la promisefin:

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

Si vous faites une demande qui pourrait également échouer, vous pouvez même aller plus loin:

$.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"?' );
    } );
kaiser
la source
2
Cette partie de cette réponse en utilisant $.when()ne fonctionne pas car myEvent()ne retourne pas de promesse et $.when()attend de vous que vous lui passiez une ou plusieurs promesses pour qu'elle fasse son travail.
jfriend00
6

si c'est quelque chose que vous souhaitez changer, en fondu un et en fondu un autre au même endroit, vous pouvez placer un attribut {position: absolute} sur les divs, de sorte que les deux animations se jouent l'une sur l'autre, et vous n'avez pas d'attendre la fin d'une animation avant de démarrer la suivante.

Samin
la source