我的代码:
<?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>
我期待第二个函数等待第一个函数完成,也就是说,我的输出应该是
begin aaa
<--pause
done, m=1
begin bbb
<--pause
done, m=5
OK
相反,我正在
begin aaa
begin bbb
<--pause
done, m=1
<--pause
done, m=5
OK
我想我误解了一些关于推迟如何工作的基本信息 - 任何人都可以解决这个问题吗?
答案 0 :(得分:7)
如果它们之间没有依赖关系,您如何期望它们按顺序执行? $.when
没有也不会对承诺的评估产生影响,只是等待每个承诺得到解决。
您的代码比它需要的更复杂。 $.ajax
已经返回一个在收到Ajax响应时得到解决的promise,因此您可以从函数中返回它。如果您想按顺序执行它们,可以通过.then
链接它们:
这些过滤器函数可以返回一个新值,传递给promise的
.done()
或.fail()
回调,或者它们可以返回另一个可以通过其已解析的可观察对象(Deferred,Promise等) /拒绝状态和承诺的回调值。
所以你的代码简化为:
function aaa() {
w("begin aaa");
return $.ajax({
type: "GET",
data: {
m: 5
}
}).done(w);
}
function bbb() {
w("begin bbb");
return $.ajax({
type: "GET",
data: {
m: 1
}
}).done(w);
}
aaa().then(bbb).done(function() { w('ok'); });
在这里,aaa().then(bbb)
创建了您需要的依赖关系。它基本上意味着“一旦aaa
的承诺得到解决,执行bbb
”。此外,.then
返回一个新的promise,当bbb
返回的promise被解析时,它会被解析,这允许你在aaa
和{{的承诺时执行一个函数。 1}}已解决。
也许这些可以帮助您更好地理解承诺(和延期):
没有bbb
的示例:
$.ajax
答案 1 :(得分:1)
$.when()
不会对其参数施加任何顺序 - 它们实际上是一个“无序列表”。
但是,.done()
,.fail()
和.then()
确实强制执行。
首先,通过修改aaa()
和bbb()
来简化事情,以返回$.ajax().done()
链返回的与Promise兼容的对象,如下所示:
function aaa() {
w("begin aaa");
return $.ajax({
type: "GET",
data: { m: 5 }
}).done(w);//without changing anything, w can be passed rather than called from an anonymous function.
}
function bbb() {
w("begin bbb");
return $.ajax({
type: "GET",
data: { m: 1 }
}).done(w);//without changing anything, w can be passed rather than called from an anonymous function.
}
现在,为了获得您所寻求的效果,请使用.then()
对aaa
和bbb
进行排序:
$(function() {
aaa().then(bbb).done(function() {
w("OK");
});
});
我同意这里有点令人困惑的是aaa
被执行并且bbb
被传递,但这是一个非常常见的模式,你会一次又一次地遇到。最终它会有意义。
要使aaa
和bbb
彼此相提并论,您可以写下以下内容:
$(function() {
$.Deferred().resolve().then(aaa).then(bbb).done(function() {
w("OK");
});
});