普通异步调用:
$.ajax({
url: "test.html",
success: function(){
alert("哈哈,成功了!");
},
error:function(){
alert("出错啦!");
}
});
延迟对象的使用:
$.ajax("test.html")
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
添加多个回调:
$.ajax("test.html")
.done(function(){ alert("哈哈,成功了!");} )
.fail(function(){ alert("出错啦!"); } )
.done(function(){ alert("第二个回调函数!");} );
集成多个回调:
$.when($.ajax("test1.html"), $.ajax("test2.html"))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
普通带回调的函数用延迟对象改造:
var wait = function(){
var dtd = $.Deferred(); // 新建一个deferred对象
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
};
setTimeout(tasks,5000);
return dtd;
};
延迟对象本质就是个状态机,jQuery规定,deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)。
刚开始创建的Promise对象处于pending状态,只能从pending变成resolved或者是从pending变成rejected状态。
dtd.resolve()的意思是,将dtd对象的执行状态从"未完成"改为"已完成",从而触发done()方法。
deferred.reject()方法,作用是将dtd对象的执行状态从"未完成"改为"已失败",从而触发fail()方法。
状态的改变是固定的从"未完成"改为"已完成"或者从"未完成"改为"已失败"不能逆向改变。
progress()和notify()能够用来实现进度条效果,因为notify()允许调用多次,而reject()和resolve()只能调用一次。这个很好理解,因为一旦状态变成resolved或者是rejected,就不能再改变其状态,也没有必要。
延迟对象暴露后可能被外部改变状态:
var wait = function(dtd){
var dtd = $.Deferred(); // 新建一个Deferred对象
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
return dtd;
};
$.when(wait(dtd))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
dtd.resolve();
为了避免这种情况,jQuery提供了deferred.promise()方法。它的作用是,在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。
var wait = function(dtd){
var dtd = $.Deferred(); // 新建一个Deferred对象
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
return dtd.promise(); // 返回promise对象
};
var d = wait(dtd); // 新建一个d对象,改为对这个对象进行操作
$.when(d)
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
d.resolve(); // 此时,这个语句是无效的
有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
$.when($.ajax( "/main.php" ))
.then(successFunc, failureFunc );
deferred.always()
这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
$.ajax( "test.html" )
.always( function() { alert("已执行!");} );
进度提示示例:
html元素:
<div id="test1"></div>
<div id="test2"></div>
<button οnclick="runDtdDemo('test1');">test1</button>
<button οnclick="runDtdDemo('test2');">test2</button>
js脚本:
function dtdDemo(){
var dtd = $.Deferred();
var counter = 0,
doStep = function(){
counter++;
dtd.notify(counter + dtd.state());
if(counter >= 100){
clearInterval(intervalId);
counter = 0;
dtd.resolve({state:dtd.state()});
}
};
var intervalId = setInterval(doStep,100);
return dtd.promise();
}
function runDtdDemo(el){
var mydtd = dtdDemo()
.progress(function(progress){
$("#"+el).html(progress);
})
.done(function(result){
$("#"+el).html("ok!" + mydtd.state());
});
}