deferred是什么?
deferred 翻譯為推遲,在jQuery 1.5中引入的Deferred對象是通過調(diào)用jQuery.Deferred()方法創(chuàng)建的可鏈接實用程序?qū)ο蟆K梢栽诨卣{(diào)隊列中注冊多個回調(diào)函數(shù)对供,調(diào)用回調(diào)隊列,并中繼任何同步或異步函數(shù)的成功或失敗狀態(tài)笔宿。
deferred能為我們解決什么問題犁钟?
我們常常會遇到這種問題,
定義一個變量泼橘, 在a函數(shù)中為它賦值 涝动,在b函數(shù)中調(diào)用它 。
如下場景:
var current = 0;
function a() {
setTimeout(function () {
current = 6;
}, 500);
}
function b() {
a();
console.log(current);
}
b(); // 0
b函數(shù)沒有等待a函數(shù)賦值成功便執(zhí)行了炬灭,導致console出的值是current 的初始值醋粟。
為了解決這個問題,我們肯定想到回調(diào)重归。
var current = 0;
function a(callback) {
setTimeout(function () {
current = 6;
callback();
}, 500);
}
function b() {
a(function(){
console.log(current);
});
}
b(); // 0
通過回調(diào)函數(shù)米愿,b函數(shù)得到了賦值6。
那么有更多的函數(shù)在b函數(shù)之前對current 賦值鼻吮,那么....
function b() {
a(function(){
c(function(){
d(function(){
console.log(current);
})
})
});
}
上面的情況讓我們的代碼變的復(fù)雜育苟、可讀性很差。
而deferred對象的產(chǎn)生是為jQuery回調(diào)函數(shù)提供解決方案椎木。
$.when(a, c, d)
.then(b);
這樣既簡化了代碼违柏,可讀性也增強了很多。_
jQuery deferred使用方法及使用場景香椎?
Deferred對象是可鏈接的漱竖,類似于jQuery對象是可鏈接的,但它有自己的方法畜伐。創(chuàng)建Deferred對象后馍惹,可以使用以下任何方法,直接從對象創(chuàng)建鏈接或?qū)ο蟊4嬖谧兞恐性僬{(diào)用該變量創(chuàng)建一個或多個方法玛界。
deferred.always()
當Deferred對象被resolved或rejected時万矾,將會調(diào)用的函數(shù)。
deferred.catch()
當Deferred對象被rejected時慎框,將會調(diào)用的函數(shù)勤众。
deferred.done()
當Deferred對象被resolved時,將會調(diào)用的函數(shù)鲤脏。
deferred.fail()
當Deferred對象被rejected時们颜,將會調(diào)用的函數(shù)。
deferred.isRejected()
測定Deferred對象是否已被rejected猎醇。
deferred.isResolved()
測定Deferred對象是否已被resolved窥突。
deferred.notify()
根據(jù)給定的 args參數(shù) 調(diào)用Deferred對象上進行中的回調(diào)
deferred.notifyWith()
根據(jù)給定的文本和args參數(shù) 調(diào)用Deferred對象上進行中的回調(diào)
deferred.pipe()
用用于過濾 and/or 鏈式Deferred對象的工具方法。
deferred.progress()
當Deferred對象生成正在執(zhí)行中的進度通知時, 將會調(diào)用的函數(shù)硫嘶。
deferred.promise()
返回Deferred Promise對象阻问。
deferred.reject()
根據(jù)給定的 args參數(shù) Reject Deferred對象并調(diào)用所有失敗回調(diào)函數(shù)。
deferred.rejectWith()
根據(jù)給定的文本和args參數(shù) Reject Deferred對象并調(diào)用所有失敗回調(diào)函數(shù)沦疾。
deferred.resolve()
根據(jù)給定的 args參數(shù) Resolve Deferred對象并調(diào)用所有成功回調(diào)函數(shù)称近。
deferred.resolveWith()
根據(jù)給定的文本和args參數(shù) Resolve Deferred對象并調(diào)用所有成功回調(diào)函數(shù)第队。
deferred.state()
測定Deferred對象的當前狀態(tài)。
deferred.then()
當Deferred對象被rejected刨秆、resolve凳谦、正在進行中時,將會調(diào)用的函數(shù)衡未。
jQuery.when()
為一種基于零個或多個對象(通常為表示異步事件的Deferred對象)提供執(zhí)行回調(diào)函數(shù)的方法尸执。
.promise()
返回一個Promise對象以觀察綁定到集合的某個類型的所有操作何時完成。
deferred對象使用resolve()函數(shù)改變了Deferred對象的當前狀態(tài)為完成并執(zhí)行與done()相關(guān)的函數(shù)缓醋。reject()函數(shù)改變了Deferred對象的當前狀態(tài)為失敗并執(zhí)行與fail()相關(guān)的函數(shù)如失。
下面是一個關(guān)于deferred的簡單例子:
var dtd = $.Deferred(); //生成一個deferred對象。
var wait =function(dtd){ //定義函數(shù) 并傳入deferred對象送粱。
alert("執(zhí)行了"); //函數(shù)體
dfd.resolve(); //手動改變deferred對象的運行狀態(tài)從“未完成”到"已完成"褪贵,立即觸發(fā)done()方法。
};
$.when(wait(dtd)) //$.when可以為多個操作指定同一個回調(diào)函數(shù) 以逗號分隔開
.done(function(){ alert("成功"); }) //指定操作成功時的回調(diào)函數(shù)
.fail(function(){ alert("失敗"); }); //指定操作失敗時的回調(diào)函數(shù)
.then(function(){ alert("成功失敗");}) //done(),fail(),progress()操作成功或失敗執(zhí)行的回調(diào)函數(shù)
暴露在外面的deferred 為全局對象抗俄,所以它的執(zhí)行狀態(tài)可以從外部改變竭鞍。為了不把 deferred 對象直接暴露出來,函數(shù)體最后需返回 deferred.promise() 返回的對象只會暴露判斷和處理狀態(tài)的方法 橄镜,而不會暴露改變狀態(tài)的方法如:
<pre>
var wait = function(){
var dtd = $.Deferred(); // 新建一個deferred對象
var tasks = function(){
alert("執(zhí)行完畢偎快!");
dtd.resolve(); // 改變deferred對象的執(zhí)行狀態(tài)
};
setTimeout(tasks, 500);
return dtd.promise();
};
$.when( wait())
.done(function(){ alert("成功"); })
.fail(function(){ alert("失敗"); });
</pre>
在ajax中應(yīng)用的實例:
<pre>
function API(api_url, method, data) {
var dtd = $.Deferred();
$.ajax({
url: api_url,
type: method,
data: data,
success: function (response) {
dtd.resolve(response);
},
error: function (error) {
dtd.reject(error);
}
});
return dtd.promise();
}
API()
.done(function (response) {
console.log('成功');
})
.fail(function (error) {
console.log('失敗');
})
</pre>
jQuery deferred的優(yōu)點:
可以給一個操作提供多個回調(diào)函數(shù)。
<pre>
complete1()
.done(function(){ alert("first success callback!");} )
.fail(function(){ alert("there is an error!"); } )
.done(function(){ alert("second success callback!");} );
</pre>
也可以給多個操作提供同一個回調(diào)函數(shù)洽胶。
<pre>
$.when(complete1() , complete2())
.done(function(){ alert("success");} )
.fail(function(){ alert("error"); } )
</pre>