请不要请说明下面的代码有什么问题(已经阅读了很多文档和示例,但仍然不知道发生了什么)
function t() {
var d = $.Deferred();
setTimeout(function(){
d.resolve();
}, 5000);
return d.promise();
}
function test() {
var dd = $.Deferred();
$.ajax("/echo/json/").done(function() {
dd = t();
dd.done(function() { alert(" dd.done inside ajax")});
});
dd.done(function() { alert(" dd.done outside ajax")});
}
test();
输出是(在~5秒内):
"dd.done inside ajax:"
为什么第二个.done无效?
答案 0 :(得分:2)
让我们看一下test()
:
function test() {
var dd = $.Deferred();
$.ajax("/echo/json/").done(function() {
dd = t();
dd.done(function() { alert(" dd.done inside ajax")});
});
dd.done(function() { alert(" dd.done outside ajax")});
}
test();
将局部变量dd
初始化为新的jQuery Deferred对象。然后,启动一个ajax操作,并给出一个“完成”回调,它将调用另一个测试函数t()
。
$.ajax()
调用将在其.done()
回调运行之前很久就立即返回。在此之后,为在函数开头创建的Deferred实例建立另一个.done()
回调。
现在,当ajax“done”回调运行时,dd
(最初创建的Deferred对象)的值将被覆盖,并且t()
返回Promise 。最终将运行.done()
回调,但没有任何东西可以解析第一个Deferred实例,因此“外部”回调永远不会发生。
答案 1 :(得分:1)
因为未解析延迟对象。您正在创建2个延迟对象并解析其中一个。
答案 2 :(得分:0)
永远不会调用您的第二个警报,因为您分配给变量dd
的原始延迟永远不会被解析,因此永远不会调用它的.done()
处理程序。
您创建了延迟并在此处将其分配给dd
:
var dd = $.Deferred();
然后,你设置了一个.done()
处理程序:
dd.done(function() { alert(" dd.done outside ajax")});
但是,当你的ajax函数完成后,你用这一行为变量dd
分配一个不同的promise:
dd = t();
因此,没有任何东西可以解析原始的承诺,因此永远不会调用它的.done()
处理程序。
我建议改用这个设计:
function t() {
var d = $.Deferred();
setTimeout(function(){
d.resolve();
}, 5000);
return d.promise();
}
function test() {
return $.ajax("/echo/json/").then(function() {
console.log("ajax call done");
return t();
}).then(function() {
console.log("after timer");
});
}
test().then(function() {
console.log("everything done");
});
工作演示:http://jsfiddle.net/jfriend00/atafc5hj/
这说明了以下有用的概念:
$.ajax()
返回的承诺,而不是创建自己的承诺。.then()
处理程序返回另一个承诺,使序列也等待该承诺。