¿Cómo hacer que jQuery espere hasta que finalice un efecto?

107

Estoy seguro de que leí sobre esto el otro día, pero parece que no puedo encontrarlo en ningún lado.
Tengo un fadeOut()evento después del cual elimino el elemento, pero jQuery está eliminando el elemento antes de que tenga la oportunidad de terminar de desvanecerse.
¿Cómo consigo que jQuery espere hasta que el elemento se haya desvanecido y luego lo elimine?

uridium
fuente

Respuestas:

167

Puede especificar una función de devolución de llamada:

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

Documentación aquí .

Paolo Bergantino
fuente
Bingo. Pensé que era eso, pero lo que tenía que hacer era poner toda mi función allí, no solo la parte de eliminación. PD: Si alguien está interesado en el libro en el que lo leí y ahora he encontrado de nuevo, es Learning JQuery - Better Interaction and Design. Gracias de nuevo
uriDium
Si alguien tiene jQuery antiguo, entonces este error de "animación hecha devolución de llamada" fue desagradable: bugs.jquery.com/ticket/5684
JustAMartin
178

Con la versión jQuery 1.6 puedes usar el .promise()método.

$(selector).fadeOut('slow');
$(selector).promise().done(function(){
    // will be called when all the animations on the queue finish
});
Reinaldo Junior
fuente
4
Esto es redundante para la mayoría de las animaciones de jQuery, ya que hay argumentos de devolución de llamada en la mayoría de los métodos, pero al usar promise()o when()y done()puedes aprovechar algunos comportamientos geniales de los métodos de terceros, o incluso los tuyos. +1 por significado .promise()!
stuartc
4
No había escuchado esto antes, solo salvé mi trasero.
prismspecs
1
en mi caso, estaba tratando de acceder a la animación actual de un elemento que estaba sucediendo en algún otro lugar de mi código y, por lo tanto, no tenía acceso a su devolución de llamada. +1
Kristian
11
El uso de promise () también le permite configurar una única devolución de llamada para cuando todo esté listo. Si llama a fadeOut () en un conjunto de 10 cosas, habrá una devolución de llamada para cada cosa con 'this' establecido en el alcance apropiado. Si solo quiere disparar una vez, esta función es realmente útil. Además: si anima en un selector que resulta coincidir con elementos cero, la devolución de llamada normal nunca se activará. Promise () se activará al final pase lo que pase.
zslayton
6
También puede encadenarlo así:$(selector).fadeOut('slow').promise().done(function(){...});
Syclone
9

También puedes usar $.when() para esperar hasta que promisetermine:

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

En caso de que esté haciendo una solicitud que también podría fallar, puede incluso ir un paso más allá:

$.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"?' );
    } );
emperador
fuente
2
Esta parte del uso de esta respuesta $.when()no funciona porque myEvent()no devuelve una promesa y $.when()espera que le pase una o más promesas para que haga su trabajo.
jfriend00
6

Si es algo que desea cambiar, desvaneciendo uno y desvaneciendo otro en el mismo lugar, puede colocar un atributo {position: absolute} en los divs, de modo que ambas animaciones se reproduzcan una encima de la otra y no tenga esperar a que termine una animación antes de iniciar la siguiente.

Samin
fuente