timer1 = $.Deferred(...)
This creates a deferred ("deferred", "deferred"). This object starts in the "pending" state. Only when someone calls the method resolve
or resolveWith
it will pass to the "resolved" state. What does this mean?
- If someone calls the method
timer1.done(função)
while their status is "pending", this function will be queued for later call;
- When this object changes from "pending" to "resolved", all queued functions will be called, in order;
- If someone calls the
timer1.done(função)
method while their status is "resolved", this function will be called immediately.
In this case, timer1
was [transformed into a promise and] used directly - with done
- and indirectly, with when
. Since it is still in the "pending" state, this means that both functions will be queued for later, and the done
will be called before the when
.
timer1 = $.Deferred(function (def) { ... }).promise();
This creates deferred and immediately calls a function that uses it in a single expression. Only that. This call above would be the equivalent of:
timer1 = $.Deferred();
(function(def) { ... }).call(timer1, timer1); // Tanto o this quanto o 1º argumento
// são o próprio Deferred
timer1 = timer1.promise();
But the status of Deferred
remains "pending," the extra function call does not necessarily change that. And indeed:
function (def) {
setTimeout(function () {
def.resolve("timer 1");
}, 2000);
}
It can be seen that this function does nothing immediately - it triggers a new function to be executed in 2 seconds (via setTimeout
), and returns. The status of deferred remains the same.
2 seconds later ...
def.resolve("timer 1");
This changes the status of timer1
to "resolved". In the case, "timer 1"
is just an argument, one could use something else, or things, or nothing. The argument (s) used in resolve
goes straight to callbacks .
As stated, changing the status of a deferred from "pending" to "resolved" devel- ops the functions associated with it and executes them. The first one is the function:
timer1.done(function (data) {
printDone(data)
});
Which - because it does not depend on anyone else - executes immediately. You should see "timer 1"
being printed on output.
The second one was created using $.when
, so it will only run when all its dependencies are resolved. timer1
is resolved, but timer2
is still pending, so this function still does not execute.
plus 2 seconds later ...
After another 2 seconds (4 total, according to the% w of% of the function used with setTimeout
), the following code is executed:
def.resolve("timer 2");
This resolves timer2
, de-parsing your callbacks and executing them, just as it did with timer2
. You should see timer1
printed on the output, since the code of "timer 2"
was the first to be queued.
Now that both done
and timer1
are in the "resolved" state, then the timer2
code is free to execute:
$.when(timer1, timer2).done(function () {
printDone('timer 1 and 2')
})
You will then see when
printed on the output. Note that this occurs before that "timer 1 and 2"
returns - because it was this call that "fired" the callbacks still pending from def.resolve("timer 2")
. This will be clear if you enter these two checks in the timers :
// Modifiquei o log pra ficar mais fácil a visualização
var log = function (msg) {
$('#output').append('<li>' + msg + '</li>');
},
printDone = function (obj) {
log(obj + ' done ..');
},
timer1 = $.Deferred(
function (def) {
setTimeout(function () {
log("Vai resolver o timer 1");
def.resolve("timer 1");
log("Resolveu o timer 1");
}, 2000);
}).promise(),
timer2 = $.Deferred(function (def) {
setTimeout(function () {
log("Vai resolver o timer 2");
def.resolve("timer 2");
log("Resolveu o timer 2");
}, 4000);
}).promise();
timer1.done(function (data) {
printDone(data)
});
timer2.done(function (data) {
printDone(data)
});
$.when(timer1, timer2).done(function () {
printDone('timer 1 and 2')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><ulid="output"></ul>