3

I was just messing around on the documentation page of jQuery.promise() and came across the following peice of code :

$("button").on("click", function () {
    $("p").append("Started...");

    $("div").each(function (i) {
        $(this).fadeIn().fadeOut(1000 * (i + 1));
    });

   $("div").promise().done(function () {
        $("p").append(" Finished! ");
    }); 
});

FIDDLE HERE

Now I do understand that $.defer in jQuery assists in Asynchronous programming, also I understand that $.done and $.fail are part of the $promise object .

I have read an interesting article HERE. There are a few good examples of how $.defer can be used to monitor css-3 transitions.

However in the fiddle example I provide, I fail to understand how $.promise picks up the fact that the transition is complete. How does promise pick up that that fadeout() is complete?

How does the below piece of code really work?

$("div").promise().done(function () {
            $("p").append(" Finished! ");
        }); 

How is promise really working here? Can anyone explain?

Dave Salomon
  • 3,287
  • 1
  • 17
  • 29
Alexander Solonik
  • 9,838
  • 18
  • 76
  • 174
  • 1
    Because all animations on matched element in set (`$('div')`) are put by default in `fx` queue, using for each animation a deferred object, which is resolved on animation complete. Once queue is empty, and all the deferred objects in queueHooks are resolved, the promise `done()` callback is fired. – A. Wolff Jul 08 '15 at 08:58
  • I added `promise` tag (and animation but...) because there is some specialists of promise on SO who could better explain it i guess – A. Wolff Jul 08 '15 at 09:01
  • @A.Wolff no probs ! thanks :) – Alexander Solonik Jul 08 '15 at 09:02
  • As a side note, this would be better way to handle animations sequentially: http://jsfiddle.net/xn9xzyx6/ See http://stackoverflow.com/a/27660144/1414562 – A. Wolff Jul 08 '15 at 09:13

2 Answers2

2

To put it simply, jQuery creates a queue of Deferred objects on each object returned by the $("div") selector (these are visible using the .data() function).
When you add some CSS animations to the divs with jQuery functions such as fadeIn() or fadeOut(), it creates Deferred objects that are appended to each individual div queues. Using$("div").promise().done() on the parent collection allows to check if all of the children Deferred object queues are empty (jQuery will iterate on the children elements).

POZ
  • 583
  • 4
  • 11
1

I haven't delved into the jQuery source, but here's my understanding.

$.promise returns a Promise which completes once all actions of a certain type have ended. By default, the 'type' is fx (source). When the fx queue is empty, the promise will resolve.

In your fiddle, you call fadeIn(), which adds the animation to the fx queue. ($.fadeIn() has queue: true by default.) $.fadeOut does the same.

When the queue is empty, the promise will resolve. This fiddle would support that. (Queue is 'inprogress' whilst the animations are running, but empty 100ms later.) A slightly more convoluted fiddle - notice how the promise completes when we clear the fx queue using $(el).queue('fx',[]);?

Dave Salomon
  • 3,287
  • 1
  • 17
  • 29