My code:
<?php
if(isset($_GET['m'])) {
$m = $_GET['m'];
sleep($m);
print "done, m=$m";
die;
}
?>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script>
function w(s) {
document.body.innerHTML = document.body.innerHTML+ "<br>" + s
}
function aaa(def) {
w("begin aaa");
$.ajax({
type: "GET",
data: {
m: 5
}
}).done(function(html) {
w(html);
def.resolve();
});
}
function bbb(def) {
w("begin bbb");
$.ajax({
type: "GET",
data: {
m: 1
}
}).done(function(html) {
w(html);
def.resolve();
});
}
$(function() {
$.when(
$.Deferred(function(d) { aaa(d) }).promise(),
$.Deferred(function(d) { bbb(d) }).promise()
).done(function() {
w("OK")
});
})
</script>
I'm expecting the second function to wait for the first one to complete, that is, my output should be
begin aaa
<--pause
done, m=1
begin bbb
<--pause
done, m=5
OK
Instead I'm getting
begin aaa
begin bbb
<--pause
done, m=1
<--pause
done, m=5
OK
I guess I'm misunderstanding something fundamental about how deferreds work - can anyone shed a light?
$.when()
doesn't impose any order on its arguments - they are effectively an "unordered list".However,
.done()
,.fail()
and.then()
do impose order.First, simplify things by amending
aaa()
andbbb()
to return the Promise-compatible object returned by the$.ajax().done()
chain, as follows :Now, to get the effect you seek, use
.then()
to sequenceaaa
andbbb
:I agree it's slightly confusing here that
aaa
is executed andbbb
is passed, but this is a very common pattern that you will encounter again and again. Eventually it will make sense.To put
aaa
andbbb
on par with each other, you could write something like :How do you expect them to be executed in order if there is no dependency between them?
$.when
doesn't have and cannot have an influence on the evaluation of the promise, it just waits until each of the promises is resolved.Your code is way more complicated then it needs to be.
$.ajax
already returns a promise which gets resolved when the Ajax response was received, so you can just return it from the functions. If you want to execute them in sequence, you can chain them via.then
:So your code simplifies to:
Here,
aaa().then(bbb)
creates the dependency you need. It basically means "onceaaa
's promise is resolved, executebbb
". In addition,.then
returns a new promise, which gets resolved when the promise returned bybbb
gets resolved, which allows you to execute a function when the promises of both,aaa
andbbb
are resolved.Maybe these help you to understand promises (and deferreds) better:
Example without
$.ajax
: