什麼是Deferred對象 javascript
defer,推遲;延期。含義就是」延遲」到將來某個點再執行。 在開發中,咱們常常遇到某些耗時很長的javascript操做。其中,既有異步的操做(好比ajax讀取服務器數據),也有同步的操做(好比遍歷一個大型數組),它們都不是當即能獲得結果的。一般的作法是,爲它們指定回調函數(callback)。即事先規定,一旦它們運行結束,應該調用哪些函數。可是,一旦回調層級過深,處理和維護會變得至關困難。jQuery開發團隊就設計了deferred對象,來做爲回調函數的解決方案。php
ajax操做的鏈式寫法 html
$.ajax({ url: "http://localhost:8888", success: function(){ console.log("哈哈,成功了!"); }, error: function(){ console.log("出錯啦!"); } });
$.ajax()操做完成後,若是使用的是低於1.5.0版本的jQuery,返回的是XHR對象,你無法進行鏈式操做;若是高於1.5.0版本,返回的是deferred對象,能夠進行鏈式操做。 java
$.ajax("http://localhost:8888") .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯啦!"); });
同一操做指定多個回調函數 ajax
$.ajax("http://localhost:8888") .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯啦!"); }) .done(function(){ console.log("第二個成功回調函數!"); });
注意:回調函數能夠添加任意多個,其按照添加順序執行。 數組
多個操做指定同一回調函數 promise
$.when($.ajax("http://localhost:8888"),$.ajax("http://localhost:9999")) .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯啦!"); });
deferred對象容許爲多個事件指定一個回調函數 ,上述示例:若是都成功了,就運行done()指定的回調函數; 若是有一個失敗或都失敗了,就執行fail()指定的回調函數。 服務器
本地操做使用回到函數 異步
var wait = function(){ var tasks = function(){ console.log("wait函數執行完畢!"); }; setTimeout(tasks, 5000); }; deferred對象,把這一套回調函數接口,從ajax操做擴展到了全部操做。
咱們想,在wait執行完,輸出」哈哈,成功了!」 因爲jQuery.when(deferreds)方法只能接收defferred對象做爲參數,因此咱們需對上述wait改寫! 函數
var dtd = $.Deferred(); // 新建一個Deferred對象 var wait = function(dtd){ var tasks = function(){ console.log("wait函數執行完畢!"); dtd.resolve(); // 改變Deferred對象的執行狀態 }; setTimeout(tasks, 5000); return dtd; // 返回deferred對象 }; $.when(wait(dtd)) .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯了!"); });
上述示例中,說起到了deferred.resolve()。說明其做用須要先說一下jQuery規定deferred對象的三種執行狀態:未完成、已完成和已失敗。
若是執行狀態是」已完成」(resolved),deferred對象馬上調用done()方法指定的回調函數;
若是執行狀態是」已失敗」,調用fail()方法指定的回調函數;
若是執行狀態是」未完成」,則繼續等待,或者調用progress()方法指定的回調函數(jQuery1.7版本添加)。
deferred.promise()方法
上面示例實現了咱們的要求:在wait執行完,輸出」哈哈,成功了!」 可是做爲JavaScript忍者,咱們是不容許這樣抒寫的,由於dtd是一個全局變量,它的執行狀態能夠從外部改變。
var dtd = $.Deferred(); // 新建一個Deferred對象 var wait = function(dtd){ var tasks = function(){ console.log("wait函數執行完畢!"); dtd.resolve(); // 改變Deferred對象的執行狀態 }; setTimeout(tasks, 5000); return dtd; // 返回deferred對象 }; $.when(wait(dtd)) .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯了!"); }); dtd.resolve();
在代碼的尾部加了一行dtd.resolve(),這就改變了dtd對象的執行狀態,所以致使done()方法馬上執行,跳出」哈哈,成功了!」的提示框,等5秒以後再跳出」wait函數執行完畢!」的提示框。 解決上述「全局變量」問題:咱們使用deferred.promise() 其做用:在原來的deferred對象上返回Promise對象,後者只開放與改變執行狀態無關的方法(好比done()方法和fail()方法),屏蔽與改變執行狀態有關的方法(好比resolve()方法和reject()方法),從而使得執行狀態不能被改變。
方式一:deferred.promise
var wait = function(){ var dtd = $.Deferred(); var tasks = function(){ console.log("wait函數執行完畢!"); dtd.resolve(); // 改變Deferred對象的執行狀態 }; setTimeout(tasks, 5000); return dtd.promise(); // 返回Promise對象 }; $.when(wait()) .done(function(){ console.log("哈哈,成功了!"); }) .fail(function(){ console.log("出錯了!"); });
方式二:在wait對象上部署deferred接口
var dtd = $.Deferred(); // 生成Deferred對象 var wait = function(dtd){ var tasks = function(){ console.log("執行完畢!"); dtd.resolve(); // 改變Deferred對象的執行狀態 }; setTimeout(tasks,5000); }; // 在wait對象上部署Deferred接口 dtd.promise(wait); wait.done(function(){ console.log("哈哈,成功了!"); }).fail(function(){ console.log("出錯啦!"); }); wait(dtd); // 調用wait函數
8、deferred對象的方法
$.Deferred() 生成一個deferred對象。
deferred.done(function(){}) 指定操做成功時的回調函數
deferred.fail(function(){}) 指定操做失敗時的回調函數
deferred.promise() 沒有參數時,返回一個新的deferred對象,該對象的運行狀態沒法被改變; 接受參數時,做用爲在參數對象上部署deferred接口。
deferred.resolve() 手動改變deferred對象的運行狀態爲」已完成」,從而當即觸發done()方法。
deferred.reject() 手動改變deferred對象的運行狀態變爲」已失敗」,從而當即觸發fail()方法。
$.when() 爲多個操做指定回調函數。
deferred.then() 有時爲了省事,能夠把done()和fail()合在一塊兒寫,這就是then()方法。
$.when($.ajax("/main.php" ))
.then(successFunc, failureFunc );
若是then()有兩個參數,那麼第一個參數是done()方法的回調函數,第二個參數是fail()方法的回調方法。
若是then()只有一個參數,那麼等同於done()。
9. deferred.always()這個方法也是用來指定回調函數的,它的做用是,無論調用的是deferred.resolve()仍是deferred.reject(),最後老是執行。
$.ajax("test.html") .always(function(){ console.log("已執行!"); });
注:本文來自大神:奮飛 的CSDN 博客 ,copy只爲了用做我的學習,收藏,方便查用。
全文地址請點擊:https://blog.csdn.net/ligang2585116/article/details/51589073