先前了解了ES6的Promise對(duì)象,來看看jQuery中的Promise,也就是jQuery的Deferred對(duì)象。
打開瀏覽器的控制臺(tái)先。
<script> var defer = $.Deferred(); console.log(defer); </script>
運(yùn)行結(jié)果:
和ES6的Promise對(duì)象長(zhǎng)的有點(diǎn)像,jQuery的Deferred對(duì)象也有resolve、reject、then方法,還有done、fail、always......方法。jQuery就是用這個(gè)Deferred對(duì)象來注冊(cè)異步操作的回調(diào)函數(shù),修改并傳遞異步操作的狀態(tài)。
玩玩Deferred:
<script> function runAsync(){ var defer = $.Deferred(); //做一些異步操作 setTimeout(function(){ console.log('執(zhí)行完成'); defer.resolve('異步請(qǐng)求成功之后返回的數(shù)據(jù)'); }, 1000); return defer; } runAsync().then(function(data){ console.log(data) }); </script>
運(yùn)行之后,Deferred對(duì)象的實(shí)例defer通過resolve方法把參數(shù) “異步請(qǐng)求成功之后返回的數(shù)據(jù)” 傳回到then方法中進(jìn)行接收,,打印。
和ES6的Promise相似,但是有一點(diǎn)點(diǎn)區(qū)別,再看下Promise:
<script> function runAsync(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ console.log('執(zhí)行完成'); resolve('異步請(qǐng)求成功之后返回的數(shù)據(jù)'); }, 1000); }); return p; } runAsync().then(function(data){ console.log(data); }); </script>
我們發(fā)現(xiàn):
1、創(chuàng)建Deferred對(duì)象的時(shí)候沒有傳參;而創(chuàng)建Promise對(duì)象的時(shí)候,傳了參數(shù)(傳了一個(gè)匿名函數(shù),函數(shù)也有兩個(gè)參數(shù):resolve、reject);
2、Deferred對(duì)象直接調(diào)用了resolve方法;而Promise對(duì)象則是在內(nèi)部調(diào)用的resolve方法;
說明:Deferred對(duì)象本身就有resolve方法,而Promise對(duì)象是在構(gòu)造器中通過執(zhí)行resolve方法,給Promise對(duì)象賦上了執(zhí)行結(jié)果的狀態(tài)。
這樣就有一個(gè)弊端:因?yàn)镈eferred對(duì)象自帶resolve方法,拿到Deferred對(duì)象之后,就可以隨時(shí)調(diào)用resolve方法,其狀態(tài)可以進(jìn)行手動(dòng)干預(yù)了
<script> function runAsync(){ var defer = $.Deferred(); //做一些異步操作 setTimeout(function(){ console.log('執(zhí)行完成'); defer.resolve('異步請(qǐng)求成功之后返回的數(shù)據(jù)'); }, 1000); return defer; } var der = runAsync(); der.then(function(data){ console.log(data) }); der.resolve('在外部結(jié)束'); </script>
這樣的話就直接在外部直接給Deferred設(shè)置了狀態(tài),打印“在外部結(jié)束”,1s后打印“執(zhí)行完成”,不會(huì)打印“異步請(qǐng)求成功之后返回的數(shù)據(jù)”了。
顯然,這不好。我發(fā)個(gè)異步請(qǐng)求,還沒收到數(shù)據(jù)就讓人在外部給我結(jié)束了。。。。
當(dāng)然這個(gè)坑jQuery肯定會(huì)填的,在Deferred對(duì)象上有一個(gè)promise方法,是一個(gè)受限的Deferred對(duì)象
<script> function runAsync(){ var def = $.Deferred(); //做一些異步操作 setTimeout(function(){ console.log('執(zhí)行完成'); def.resolve('請(qǐng)求成功之后返回的數(shù)據(jù)'); }, 2000); return def.promise(); //就在這里調(diào)用 } </script>
所謂受限的Deferred對(duì)象,就是沒有resolve和reject方法的Deferred對(duì)象。這樣就無法在外邊改變Deferred對(duì)象的狀態(tài)了。
Deferred對(duì)象的then方法和done、fail語法糖
我們知道,在ES6的Promise規(guī)范中,then方法接受兩個(gè)參數(shù),分別是執(zhí)行完成和執(zhí)行失敗的回調(diào),而jquery中進(jìn)行了增強(qiáng),還可以接受第三個(gè)參數(shù),就是在pending狀態(tài)時(shí)的回調(diào),如下:
deferred.then( doneFilter [, failFilter ] [, progressFilter ] )
then方法:
<script> function runAsync(){ var def = $.Deferred(); //做一些異步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的隨機(jī)數(shù) if(num<=5){ def.resolve(num); } else{ def.reject('數(shù)字太大了'); } }, 2000); return def.promise(); //就在這里調(diào)用 } runAsync().then(function(d){ console.log("resolve"); console.log(d); },function(d){ console.log("reject"); console.log(d); }) </script>
Deferred對(duì)象的then方法也是可以進(jìn)行鏈?zhǔn)讲僮鞯摹?/p>
done,fail語法糖,分別用來指定執(zhí)行完成和執(zhí)行失敗的回調(diào),與這段代碼是等價(jià)的:
<script> function runAsync(){ var def = $.Deferred(); //做一些異步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的隨機(jī)數(shù) if(num<=5){ def.resolve(num); } else{ def.reject('數(shù)字太大了'); } }, 2000); return def.promise(); //就在這里調(diào)用 } runAsync().done(function(d){ console.log("resolve"); console.log(d); }).fail(function(d){ console.log("reject"); console.log(d); }) </script>
always的用法
jquery的Deferred對(duì)象上還有一個(gè)always方法,不論執(zhí)行完成還是執(zhí)行失敗,always都會(huì)執(zhí)行,有點(diǎn)類似ajax中的complete。
$.when的用法
jquery中,還有一個(gè)$.when方法來實(shí)現(xiàn)Promise,與ES6中的all方法功能一樣,并行執(zhí)行異步操作,在所有的異步操作執(zhí)行完后才執(zhí)行回調(diào)函數(shù)。不過$.when并沒有定義在$.Deferred中,看名字就知道,$.when,它是一個(gè)單獨(dú)的方法。與ES6的all的參數(shù)稍有區(qū)別,它接受的并不是數(shù)組,而是多個(gè)Deferred對(duì)象,如下:
<script> function runAsync(){ var def = $.Deferred(); //做一些異步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); //生成1-10的隨機(jī)數(shù) def.resolve(num); }, 2000); return def.promise(); //就在這里調(diào)用 } $.when(runAsync(), runAsync(), runAsync()) .then(function(data1, data2, data3){ console.log('全部執(zhí)行完成'); console.log(data1, data2, data3); }); </script>
jquery中沒有像ES6中的race方法嗎?就是以跑的快的為準(zhǔn)的那個(gè)方法。對(duì)的,jquery中沒有。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com