什么是deferred對象
在開發(fā)過程中,經(jīng)常會遇到ajax請求,或者大數(shù)據(jù)處理的情況,請求的數(shù)據(jù)或處理結(jié)果不會馬上返回,通常的做法就是需要設(shè)置一個回調(diào)callback來執(zhí)行完成后的操作。
deferred操作就是jquery或zepto回調(diào)函數(shù)解決方案。
它解決了耗時操作的問題,對那些操作的方法起到了更好的控制,并且有了統(tǒng)一的接口。
介紹一下deffered的參數(shù)
- $.Deferred() 生成一個deferred對象。
- deferred.done() 指定操作成功時的回調(diào)函數(shù)
- deferred.fail() 指定操作失敗時的回調(diào)函數(shù)
- deferred.promise() 沒有參數(shù)時,返回一個新的deferred對象,該對象的運行狀態(tài)無法被改變;接受參數(shù)時,作用為在參數(shù)對象上部署deferred接口。
- deferred.resolve() 手動改變deferred對象的運行狀態(tài)為"已完成",從而立即觸發(fā)done()方法。
- deferred.reject() 這個方法與deferred.resolve()正好相反,調(diào)用后將deferred對象的運行狀態(tài)變?yōu)?已失敗",從而立即觸發(fā)fail()方法。
- $.when() 為多個操作指定回調(diào)函數(shù)。
- deferred.then()有時為了省事,可以把done()和fail()合在一起寫,這就是then()方法?!?br>
$.when($.ajax( "/main.html" )).then(successFunc, failureFunc );
如果then()有兩個參數(shù),那么第一個參數(shù)是done()方法的回調(diào)函數(shù),第二個參數(shù)是fail()方法的回調(diào)方法。如果then()只有一個參數(shù),那么等同于done()。
9.deferred.always()這個方法也是用來指定回調(diào)函數(shù)的,它的作用是,不管調(diào)用的是deferred.resolve()還是deferred.reject(),最后總是執(zhí)行。
.always( function() { alert("已執(zhí)行!");} );```
普通耗時請求 setTimeout
console.log("執(zhí)行二");```
假如想讓上面的代碼順序執(zhí)行,怎么做呢?普通方式是把后面執(zhí)行的內(nèi)容也同時包裹在setTimout里面,但是用deffered就不同了。它是通過一個包裹接口,等前置任務(wù)執(zhí)行完成再進行下一步的操作。
``` var wait2 = function(){ var tasks = function(){
alert("執(zhí)行完畢test!"); };
setTimeout(tasks,5000); };
$.when(wait2()) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出錯啦!"); }); ```
上面的方法還是會先執(zhí)行done或fail里的函數(shù),使用defferred的改寫方法如下:
``` function wait(){ var dtd = $.Deferred(); // 新建一個Deferred對象
setTimeout(function(){ console.log("執(zhí)行任務(wù)1");
dtd.resolve("1任務(wù)");// 改變Deferred對象的執(zhí)行狀態(tài) },100); return dtd.promise(); };
wait().done(function(data){ console.log(data+"執(zhí)行完成了"); });```
還有另外一種寫法
```var dtd1 = $.Deferred(); // 新建一個Deferred對象 var wait1=function(dtd){
setTimeout(function(){
console.log("執(zhí)行任務(wù)2");
dtd1.resolve("2任務(wù)");// 改變Deferred對象的執(zhí)行狀態(tài)
},100); };
dtd1.promise(wait1);
wait1.done(function(data){
console.log(data+"執(zhí)行完成了"); });
wait1(dtd1);```
### ajax請求的寫法老版本不支持deffered方法
``` $.ajax({ url: "test.html",
success: function(){ alert("哈哈,成功了!"); },
error:function(){ alert("出錯啦!"); } });```
$.ajax()操作完成后,高于1.5.0版本,返回的是deferred對象,可以進行鏈?zhǔn)讲僮鳌?``` $.ajax("test.html")
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出錯啦!"); }); ```
deferred對象的一大好處,就是它允許你自由添加多個回調(diào)函數(shù)。``` $.ajax("test.html")
.done(function(){ alert("哈哈,成功了!");} )
.fail(function(){alert("出錯啦!");} )
.done(function(){ alert("第二個回調(diào)函數(shù)!");} )
.fail(function(){ alert("真的不好意思!"); } )```
deferred對象的另一大好處,就是它允許你為多個事件指定一個回調(diào)函數(shù),這是傳統(tǒng)寫法做不到的。
``` $.when($.ajax("test1.html"),
$.ajax("test2.html"))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出錯啦!"); }); ```
jquery從1.5.0開始具有了deffered功能 ,zepto使用deffered的時候需要引入兩個插件"deferred","callbacks",把它放入zepto內(nèi)容的最低部,就OK
參考文章 [阮一峰的Deffered文章](http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html),[zepto 1.1.6 api](http://www.css88.com/doc/zeptojs_api/)