2012-03-07 13 views
11

¿Cómo puedo cancelar una promesa sin eliminar el elemento del DOM?Cancelar una promesa diferida en jQuery

fiddle

que corrió este código:

$("#box") 
    .delay(2000) 
    .show("slow") 
    .delay(2000) 
    .promise()        
    .then(function(){log("Done");}); 

Después de esto, hay una manera de cancelar la promesa? Ambos clearQueue() y stop(true) no funcionaron, porque no es una animación que intento cancelar. Vi que remove() debería hacerlo ... pero solo quiero detener la promesa, no eliminar todo el elemento.

+1

Si solo tiene el objeto promesa (y no tiene acceso al original diferido), entonces sería imposible hacerlo. La idea de una promesa es poder escuchar lo diferido que se resuelve o rechaza, sin la funcionalidad de resolución/rechazo. Lo que puede hacer es crear un envoltorio de promesa que exponga los funcionamientos de promesa originales, pero todas las devoluciones de llamada están enlazadas con una función de envoltura que escucha algún tipo de señal para evitar activar la devolución de llamada si el diferido se marca como cancelado. –

+0

casi, en realidad solo desea crear un rechazo diferido y manualmente o resolverlo como mejor le parezca. –

Respuesta

4

Buenas noticias. Desde ayer puedes cancelar tu promesa.

Publiqué la nueva versión de mi pequeño complemento jquery-timing que proporciona dos métodos entre muchos otros llamados .wait() y .unwait().

var deferred = $("#box").delay(2000).show("slow").delay(2000).promise(); 
$.wait(deferred, function(){ log("Done"); }); 

Si a continuación desea anular el registro de la devolución de llamada:

$.unwait(); 

Estas versiones estáticas de espera y unwait también el apoyo de un nombre de grupo opcional a no cancelar cualquier manejador pero sólo un conjunto específico.

Además de que se puede hacer muchas cosas más inteligente como:

$('#box').wait(deferred).addClass('ready'); 

o todo el código en una cadena, sin opción unwait:

$("#box").delay(2000).show("slow") 
    .delay(2000).join(function(){log("Done");})).addClass('ready'); 

o el mismo aún más corto con la opción de cancelar las dos pausas:

$("#box").wait(2000).show("slow",$) 
    .wait(2000, function(){log("Done");})).addClass('ready'); 

Sólo hay que ver los documentos, ejemplos, y la API de lo que se ajusta mejor para usted.

+0

solo una consulta: ¿puedo usar deferred.reject()? –

2

Creo que se puede utilizar $('#box').remove();

De la documentación de jQuery aquí: http://api.jquery.com/promise/

El regresaron Promise está vinculado a un objeto diferido almacenado en el .data() para un elemento. Como el método .remove() elimina los datos del elemento, así como el elemento en sí, evitará que se resuelva alguna de las promesas no resueltas del elemento. Si es necesario eliminar un elemento de la DOM antes de que se resuelva su promesa, utilizar .detach() en su lugar y seguir con .removeData() después de la resolución."

+0

Bueno, vi 'remove(), pero me preguntaba si hay una forma de hacerlo sin eliminar el elemento real. Pregunta editada – ripper234

+1

Sí, tener que quitar el elemento del dom no parece ideal. Era la única forma en que podía hacer que funcionara. La mejor de las suertes en su búsqueda de una mejor solución. – Paul

1

no creo que te gustaría algo como http://jsfiddle.net/2cq8M/? Estoy involucrando dos promesas (una para manejar el caso al final del conjunto de animaciones, la otra para resolver o rechazar según sea necesario).

+0

Por supuesto, lo más importante que me interesa es lo que se supone que sucederá con las animaciones una vez que rechaces la promesa. – JayC

+0

Una sintaxis un poco torpe ... Esperaba una manera de cancelar una promesa ... podría no haber una forma en la implementación actual. – ripper234

1

En este caso, desea utilizar un diferido en lugar de una promesa, sin embargo, puede utilizar la promesa de la animación para resolver el aplazado.

http://jsfiddle.net/LG9eZ/9/

var stopDone = true; 

function log(msg) { 
    $(".debug").append(new Date() + " - " + msg + "<br/>"); 
} 

log("Starting"); 

var boxAnimation = new $.Deferred(); 
boxAnimation.done(function() { 
    log("Done"); 
}); 
boxAnimation.fail(function() { 
    log("Stopped"); 
}); 


$("#box").delay(2000).show("slow").delay(2000).promise().then(function() { 
    boxAnimation.resolve(); // when all the animations are done, resolve the deferred. 
}); 


if (stopDone) 
{ 
    boxAnimation.reject(); 
} 

Como nota al margen, los diferidos solo se pueden rechazar o resolver una vez. Una vez que son rechazados o resueltos, no puede cambiar su estado.

Cuestiones relacionadas