延遲對象,在jQuery的1.5引入,是經過調用jQuery.Deferred()方法建立一個可鏈式調用的工具對象。 它能夠註冊多個回調到回調隊列, 調用回調隊列,準備代替任何同步或異步函數的成功或失敗狀態。——jQuery API中文文檔
簡單說,deferred對象就是jQuery的回調函數解決方案。在英語中,defer的意思是"延遲",因此deferred對象的含義就是"延遲"到將來某個點再執行。它解決了如何處理耗時操做的問題,對那些操做提供了更好的控制,以及統一的編程接口。——阮一峯
ajax 操做的鏈式寫法php
$.ajax("test.html") .done(function(){ alert("success"); }) .fail(function(){ alert("error"); });
$.ajax()
操做完成後,若是使用的是低於1.5.0版本的jQuery,返回的是XHR對象,沒法進行鏈式操做;若是是高於1.5.0版本,返回的是deferred對象,能夠進行鏈式操做。能夠看到,done()
至關於 success
方法,fail()
至關於 error
方法。採用鏈式寫法之後,代碼的可讀性大大提升。css
這裏着重強調一下 jqXHR 對象,從 jQuery 1.5 開始, $.ajax()
返回的 jqXHR對象 自己就是 deferred 對象,所以能夠像上面代碼中那樣進行鏈式調用。html
從 jQuery 1.5 開始,$.ajax()返回的jqXHR對象 實現了 Promise 接口, 使它擁有了 Promise 的全部屬性,方法和行爲。(見Deferred object獲取更多信息)。爲了讓回調函數的名字統一,便於在$.ajax()中使用。jqXHR也提供.error() .success()和.complete()方法。這些方法都帶有一個參數,該參數是一個函數,此函數在 $.ajax()請求結束時被調用,而且這個函數接收的參數,與調用 $.ajax()函數時的參數是一致。這將容許你在一次請求時,對多個回調函數進行賦值,甚至容許你在請求已經完成後,對回調函數進行賦值(若是該請求已經完成,則回調函數會被馬上調用)。
注意事項: jqXHR.success()
, jqXHR.error()
, 和 jqXHR.complete()
回調從 jQuery 1.8開始 被棄用過期,從jQuery 3.0開始被刪除,你可使用 jqXHR.done()
, jqXHR.fail()
, 和 jqXHR.always()
代替。jquery
指定同一操做的多個回調函數
deferred 對象的一大好處,就是它容許你自由添加多個回調函數。仍是以上面的代碼爲例,若是ajax操做成功後,除了原來的回調函數,我還想再運行一個回調函數,怎麼辦?很簡單,直接把它加在後面就好了。程序員
$.ajax("test.html") .done(function(){ alert('success'); }) .fail(function(){ alert('error'); }) .done(function(){ alert('第二個回調函數!'); });
回調函數能夠添加任意多個,它們按照添加順序執行。web
爲多個操做指定回調函數
deferred 對象的另外一大好處,就是它容許你爲多個事件指定一個回調函數,這是傳統寫法作不到的。ajax
請看下面的代碼,它用到了一個新的方法 jQuery.when():編程
$.when($.ajax("test1.html"), $.ajax("test2.html")) .done(function(){ alert('success'); }) .fail(function(){ alert('error'); });
這段代碼的意思是,先執行兩個操做$.ajax("test1.html")和$.ajax("test2.html"),若是都成功了,就運行done()指定的回調函數;若是有一個失敗或都失敗了,就執行fail()指定的回調函數。api
$.when() 方法的使用具體 參見文檔。promise
普通操做的回調函數接口
deferred 對象的最大優勢,就是它把這一套回調函數接口,從ajax操做擴展到了全部操做。也就是說,任何一個操做----不論是ajax操做仍是本地操做,也不論是異步操做仍是同步操做----均可以使用deferred對象的各類方法,指定回調函數。
咱們來看一個具體的例子,爲一個很耗時的操做 wait 指定回調函數:
var wait = function (dtd) { var dtd = $.Deferred(); // 在函數內部,新建一個Deferred對象 var tasks = function () { alert('執行完畢!'); dtd.resolve(); // 改變Deferred對象的執行狀態 }; setTimeout(tasks, 5000); return dtd.promise(); // 返回promise對象 }; $.when(wait()) .done(function () { alert('success'); }) .fail(function () { alert('error'); });
另外一種作法是直接將 wait 函數傳入 $.Deferred()
:
$.Deferred(wait) .done(function(){ alert('success'); }) .fail(function(){ alert('error'); });
jQuery 規定,$.Deferred()
能夠接受一個函數名(注意,是函數名)做爲參數,$.Deferred()
所生成的 deferred 對象將做爲這個函數的默認參數。
更具體的信息請參見 阮一峯的文檔。
$.Deferred()
生成一個 deferred 對象。jQuery.Deferred( [beforeStart ] )
工廠函數建立一個新的deferred對象。
描述: 一個工廠函數,這個函數返回一個鏈式實用對象,用返回對象方法來在回調隊列中註冊多個回調, 調用回調隊列,傳遞任何同步或異步函數的成功或失敗狀態。
beforeStart
: 類型 Function( Deferred deferred )
,一個構造函數返回以前調用的函數。
jQuery.Deferred
方法能夠傳遞一個可選的函數, 這個函數在方法返回以前調用, 而且會把新的 deferred(延遲)對象做爲 this 對象,將其做爲第一個參數傳遞給函數。例如,被調用的函數可使用deferred.then()
綁定回調。
deferred.done()
指定操做成功時的回調函數。deferred.fail()
指定操做失敗時的回調函數。deferred.promise()
沒有參數時,返回一個新的 deferred。 對象,該對象的運行狀態沒法被改變;接受參數時,做用爲在參數對象上部署 deferred 接口。deferred.resolve()
手動改變 deferred 對象的運行狀態爲"已完成",從而當即觸發 done()
方法。
一個 Deferred(延遲)對象開始於 pending 狀態。 任何回調使用deferred.then()
,deferred.always()
,deferred.done()
, 或者deferred.fail()
添加到這個對象都是排隊等待執行。調用deferred.resolve()
轉換 Deferred(遞延)到 resolved(解決)的狀態,並當即執行設置中任何的 doneCallbacks。調用deferred.reject()
轉換 Deferred(遞延)到 rejected(拒絕)的狀態,並當即執行設置中任何的 failCallbacks。一旦對象已經進入瞭解決或拒絕狀態,它處於該狀態。回調仍然能夠添加到解決或拒絕 Deferred(遞延)- 他們會當即執行。
$.ajax()
返回的 jqXHR 對象 會根據請求返回的結果,自動改變自身的執行狀態。可是,對於其餘經過 $.Deferred()
方法生成的 deferred 對象,它們的執行狀態必須由程序員手動指定,由代碼決定在何時觸發回調函數。
deferred.reject()
這個方法與 deferred.resolve()
正好相反,調用後將 deferred 對象的運行狀態變爲"已失敗",從而當即觸發 fail()
方法。$.when()
爲多個操做指定回調函數。deferred.then()
方法
有時爲了省事,能夠把 done()
和 fail()
合在一塊兒寫,這就是 then()
方法。
$.when($.ajax( '/main.php' )) .then(successFunc, failureFunc);
若是 then()
有兩個參數,那麼第一個參數是 done()
方法的回調函數,第二個參數是 fail()
方法的回調方法。若是 then()
只有一個參數,那麼等同於 done()
。
deferred.always()
方法
這個方法也是用來指定回調函數的,它的做用是,無論調用的是 deferred.resolve()
仍是 deferred.reject()
,最後老是執行。
$.ajax( 'test.html' ) .always( function() { alert('已執行!');} );
更多信息請參見 jQuery API中文文檔。