Canceling a Deferred Promise in jQuery

2020-08-14 07:45发布

How can I cancel a promise without removing the element from the DOM?

fiddle

I ran this code:

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

After this, is there a way to cancel the promise? Both clearQueue() and stop(true) didn't work, because it's not an animation that I'm trying to cancel. I saw that remove() should do it ... but I only want to stop the promise, not remove the entire element.

4条回答
戒情不戒烟
2楼-- · 2020-08-14 07:56

Good news. Since yesterday you can cancel your promise.

I published the new version of my small plugin jquery-timing that provides two methods amongst many others called .wait() and .unwait().

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

If you then want to unregister the callback:

$.unwait();

These static versions of wait and unwait also support an optional group name to not cancel any handler but only a specific set.

Besides that you can do a lot more smart stuff like:

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

or the whole code in one chain, without unwait option:

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

or the same even shorter with option to cancel the two pauses:

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

Just see the docs, examples, and API what fits best for you.

查看更多
迷人小祖宗
3楼-- · 2020-08-14 07:56

I don't suppose you'd want something like http://jsfiddle.net/2cq8M/ ? I'm involving two promises (one just to handle the case at the end of the set of animations, the other to resolve or reject as needed).

查看更多
smile是对你的礼貌
4楼-- · 2020-08-14 08:05

I believe you can use $('#box').remove();

From the jQuery documentation here: http://api.jquery.com/promise/

The returned Promise is linked to a Deferred object stored on the .data() for an element. Since the .remove() method removes the element's data as well as the element itself, it will prevent any of the element's unresolved Promises from resolving. If it is necessary to remove an element from the DOM before its Promise is resolved, use .detach() instead and follow with .removeData() after resolution."

查看更多
Bombasti
5楼-- · 2020-08-14 08:12

You want to use a deferred in this case instead of a promise, however, you can use the promise of the animation to resolve the deferred.

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

As a side note, deferreds can only rejected or resolved once. Once they are rejected or resolved, you cannot change their state.

查看更多
登录 后发表回答