javascript --- jQuery --- Deferred對象
defer - Bing 字典:v.遷延;聽從;扣存;【軍】使延期入伍所以deferred對象的含義就是"延遲"到未來某個點再執行。 jQuery的官方文檔給出了用jQuery.ajax()發送請求的基本方式http://api.jquery.com/jQuery.ajax/Example: Save some data to the server and notify the user once it's complete. 服務端需要接收資料,這裡為了方便起見,我們請求一個靜態檔案sample.htmlsample.html的內容如下:\jQuery_Deferred\sample.html <!DOCTYPE html><html><body> Ajax請求返回的資料!</body></html>這裡的ajax方法請求的是靜態檔案sample.html\jQuery_Deferred\deferred1.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>Ajax Example</title> <script src="jquery-2.1.1.js"></script></head><body><script> $.ajax({ type: "POST", url: "sample.html", data: { name: "John", location: "Boston" } }).done(function (msg) { alert("Data Saved: " + msg); });</script></body></html>複製代碼 用瀏覽器開啟後,可以看到如下的結果:picture 本文參考了阮一峰的日誌:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.htmldeferred對象徹底改變了在jQuery中使用ajax如果對ajax陌生,可以參考我以前寫的日誌:http://www.cnblogs.com/kodoyang/p/Javascript_Ajax_XMLHttpRequest_Encapsulation.html deferred對象就是jQuery的回呼函數解決方案下面是阮一峰部落格的原文: <span style="font-size: 16px;">開發網站的過程中,我們經常遇到某些耗時很長的javascript操作。 其中,既有非同步操作(比如ajax讀取伺服器資料), 也有同步的操作(比如遍曆一個大型數組),它們都不是立即能得到結果的。通常的做法是,為它們指定回呼函數(callback)。 即事先規定,一旦它們運行結束,應該調用哪些函數。 它解決了如何處理耗時操作的問題, 對那些操作提供了更好的控制,以及統一的編程介面。</span>}jQuery的ajax的傳統寫法如下:jQuery的線上API 文檔: http://jquery.cuishifeng.cn/\jQuery_Deferred\deferred2.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>Traditional Ajax</title> <script src="jquery-2.1.1.js"></script></head><body><script> $.ajax({ url: "test.html", context: document.body, success: function () { $(this).addClass("done"); } });</script></body></html>複製代碼\jQuery_Deferred\test.html <p>success data!</p>使用Deferred對象的鏈式操作,寫法如下:\jQuery_Deferred\deferred3.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>Deferred Ajax</title> <script src="jquery-2.1.1.js"></script></head><body> <script> $.ajax("test1.html") .done(function(data){ alert(data); }) .fail(function(){ alert("error!"); }); </script></body></html>複製代碼這裡$.ajax()返回的是deferred對象 deferred對象允許自由添加多個回呼函數\jQuery_Deferred\deferred4.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>Deferred add callback function</title> <script src="jquery-2.1.1.js"></script></head><body><script> $.ajax("test.html") .done(function(data){ alert(data); }) .fail(function(){ alert("error!"); }) .done(function(){ alert("haha, success!"); });</script></body></html>複製代碼deferre對象允許為多個事件指定一個回呼函數當兩個操作都返回成功時,運行done()指定的回呼函數 \jQuery_Deferred\deferred5.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>above one request</title> <script src="jquery-2.1.1.js"></script></head><body><script> $.when($.ajax("test.html"), $.ajax("sample.html")) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出錯啦!"); });</script></body></html>複製代碼使用普通操作的回呼函數介面\jQuery_Deferred\deferred6.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>general function</title> <script src="jquery-2.1.1.js"></script></head><body><script> var wait = function(){ setTimeout(function(){ alert("執行完畢!"); }, 5000); }</script></body></html>複製代碼我們應該怎樣為它指定回呼函數?$.ajax返回的是deferred對象,所以可以鏈式調用 具體的細節可以查看阮一峰的日誌,我這裡給出最後的寫法:\jQuery_Deferred\deferred7.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>final code</title> <script src="jquery-2.1.1.js"></script></head><body><script> /** * Deferred對象有三種執行狀態: * 未完成: * 繼續等待,或者調用progress()方法指定的回呼函數 * 已完成: * deferred.resolve() 調用後 * deferred對象立刻調用done()方法指定的回呼函數 * 已失敗: * deferred.reject() 調用後 * 調用fail()方法指定的回呼函數 * * Deferred.promise函數: * 避免Deferred對象的“執行狀態”在外部發生改變 * 它的作用是,在原來的deferred對象上返回另一個deferred對象, * 後者只開放與改變執行狀態無關的方法(比如done()方法和fail()方法), * 屏蔽與改變執行狀態有關的方法(比如resolve()方法和reject()方法), * 從而使得執行狀態不能被改變。 * * @returns 不能改變執行狀態的Deferred對象 */ function wait(){ // 在函數內部,建立一個Deferred對象 var deferred = $.Deferred(); setTimeout(function(){ alert("執行完畢!"); // 改變Deferred對象的執行狀態 deferred.resolve(); }, 5000); // 返回promise對象 return deferred.promise(); } /** * 接受一個Deferred對象, * 當檢測到對象的執行狀態發生改變後,調用相應的函數 */ $.when(wait()) .done(function(){ alert("hahah, 成功了!"); }) .fail(function(){ alert("aaouu,出錯了!") });</script></body></html>複製代碼最後介紹一下Deferred.alway()函數不管調用的是deferred.resolve()還是deferred.reject(),最後總是執行。\jQuery_Deferred\deferred8.html 複製代碼<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>reject then always</title> <script src="jquery-2.1.1.js"></script></head><body><script> /** * 這個方法也是用來指定回呼函數的,它的作用是, * 不管調用的是deferred.resolve()還是deferred.reject(), * 最後總是執行。 */ $.when($.ajax("test1.html")) .always(function(data){ alert("已執行:" + data); });</script></body></html>