摘要:把回調(diào)函數(shù)寫(xiě)法分離出來(lái),在異步操作執(zhí)行完后,用鏈?zhǔn)秸{(diào)用的方法執(zhí)行回調(diào)函數(shù),對(duì)于多層回調(diào)來(lái)說(shuō),非常的方便,可以繼續(xù)在的方法中繼續(xù)寫(xiě)對(duì)象并返回,繼續(xù)調(diào)用來(lái)進(jìn)行回調(diào)操作,這就是的作用。
Promise是什么
JS就是操作對(duì)象上的屬性和方法,對(duì)于一個(gè)對(duì)象,想要了解,我們可以直接從其身上的屬性和方法入手;直接使用console.dir(對(duì)象)打印出來(lái)
從上面打印出來(lái)的屬性和方法,可以看到Promise是一個(gè)構(gòu)造函數(shù),有屬于自己私有的all,reject,resolve,rece等方法,也有原型上面的,屬于實(shí)例對(duì)象調(diào)用的方法then,catch
// Promise里面?zhèn)魅胍粋€(gè)函數(shù)類(lèi)型的參數(shù),這個(gè)函數(shù)類(lèi)型的參數(shù)接收兩個(gè)參數(shù)resolve reject var p=new Promise(function(resolve,reject){ // 異步操作 setTimeout(function(){ console.log("icessun"); // 兩秒之后打印出icessun resolve("icessun2"); // resolve是成功后的回調(diào)函數(shù) 里面的icessun2是傳入的參數(shù) },2000) }); // 那么p是一個(gè)實(shí)例對(duì)象,可以使用then方法(Promise原型上面的方法) p.then(function(){ console.log(arguments); // 會(huì)打印出一個(gè)類(lèi)數(shù)組 ["icessun2"] }) p.then(function(data){ console.log(data); // 會(huì)打印出icessun2 data接收了resolve里面的參數(shù) })
對(duì)于上面這段代碼,首先new一個(gè)實(shí)例對(duì)象賦值給p,Promise的構(gòu)造函數(shù)接受一個(gè)參數(shù),是函數(shù);并且傳入兩個(gè)參數(shù):resolve,reject,分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù);然后里面設(shè)置一個(gè)定時(shí)器setTimeout,開(kāi)啟一個(gè)異步操作,兩秒后輸出icessun,并且調(diào)用resolve方法,注意一個(gè)細(xì)節(jié):
上面的代碼,只是new了一個(gè)對(duì)象實(shí)例,并沒(méi)有調(diào)用,就執(zhí)行了;對(duì)于這個(gè)情況,一般是把其嵌套在一個(gè)函數(shù)里面,避免立即執(zhí)行,在需要的時(shí)候去運(yùn)行這個(gè)函數(shù)。
p 是一個(gè)實(shí)例對(duì)象,可以使用then方法,其里面的函數(shù)是對(duì)于resolve或者reject的調(diào)用的體現(xiàn),可以接收resolve,reject傳入的參數(shù)
function icessun(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ console.log("icessun"); reslove("icessun2"); },2000); }); return p; // 返回p實(shí)例,使其可以使用Promise原型上面的方法 } icessun(); // 調(diào)用執(zhí)行icessun函數(shù) 得到一個(gè)Promis對(duì)象 // 也可以直接這樣調(diào)用 icessun().then(function(data){ console.log(data); // icessun2 // 一些其他的操作 // ..... });
通過(guò)上面的代碼,知道then里面的函數(shù)就是經(jīng)常說(shuō)的回調(diào)函數(shù)callback,在icessun這個(gè)異步任務(wù)執(zhí)行完成后被執(zhí)行。把回調(diào)函數(shù)寫(xiě)法分離出來(lái),在異步操作執(zhí)行完后,用鏈?zhǔn)秸{(diào)用的方法執(zhí)行回調(diào)函數(shù),對(duì)于多層回調(diào)來(lái)說(shuō),非常的方便,可以繼續(xù)在then的方法中繼續(xù)寫(xiě)Promise對(duì)象并返回,繼續(xù)調(diào)用then來(lái)進(jìn)行回調(diào)操作,這就是Promise的作用。
鏈?zhǔn)讲僮?/b>從上面看,Promise對(duì)于多層回調(diào),可以簡(jiǎn)化其寫(xiě)法,使得更加的語(yǔ)義化;但是Promise的精髓在于其鏈?zhǔn)讲僮鳎瑐鬟f狀態(tài),維護(hù)狀態(tài)的方式使得回調(diào)函數(shù)能夠及時(shí)的調(diào)用。打開(kāi)Promise的正確場(chǎng)景是這樣:
function runAsync1(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ console.log("執(zhí)行完成1") resolve("icessun1"); },2000); }); return p; // 返回p實(shí)例對(duì)象 } function runAsync2(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ console.log("執(zhí)行完成2") resolve("icessun2"); },2000); }); return p; // 返回p實(shí)例對(duì)象 } function runAsync3(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ console.log("執(zhí)行完成3") resolve("icessun3"); },2000); }); return p; // 返回p實(shí)例對(duì)象 } // 正確的打開(kāi)Promise的方法 runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return runAsync3(); }) .then(function(data){ console.log(data); })
這樣能夠按照順序,每隔兩秒輸出每個(gè)異步回調(diào)中的內(nèi)容,運(yùn)行結(jié)果:
當(dāng)然我們可以直接return數(shù)據(jù)而不是Promise對(duì)象,在后面的then方法就可以直接接收到數(shù)據(jù),如下:
// 正確的打開(kāi)Promise的方法 runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return "我是直接返回的數(shù)據(jù)"; }) .then(function(data){ console.log(data); })reject的用法
前面我們說(shuō)了resolve是執(zhí)行成功的回調(diào),那么reject就是執(zhí)行失敗的回調(diào),將Promise的狀態(tài)設(shè)置為rejected,這樣就可以在then里面獲取到,執(zhí)行失敗情況下的回調(diào)。
function getNumber(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ var num=Math.ceil(Math.random()*10); // 生成1-10 之間的隨機(jī)數(shù) Math.ceil(): 大于或等于給定數(shù)字的最小整數(shù) if(num<=5){ resolve(num); }else{ reject("數(shù)字太大了") } },2000); }); return p; } getNumber() .then(function(data){ console.log("resolved"); console.log(data); },function(reason,data){ console.log("resolved"); console.log(reason); // 數(shù)字太大 console.log(data); // undefined });
getNumber()函數(shù)執(zhí)行后會(huì)出現(xiàn)兩種情況,要么大于5,要么小于5,在then中傳入了兩個(gè)參數(shù),第一個(gè)是對(duì)應(yīng)resolve的回調(diào),第二個(gè)是對(duì)應(yīng)reject的回調(diào)。
catch的用法看到這個(gè)方法,就會(huì)想到瀏覽器處理異常的try...catch()方法,有錯(cuò)誤進(jìn)入catch方法,不阻斷程序的執(zhí)行,其實(shí)這個(gè)方法也是來(lái)處理錯(cuò)誤的,用來(lái)指定reject的回調(diào),防止程序錯(cuò)誤,阻斷后面程序的執(zhí)行,使其能夠繼續(xù)執(zhí)行。
getNumber() .then(function(data){ console.log("resolve"); console.log(data); }) .catch(function(data){ console.log("reject"); console.log(data); })
其效果和上面在then里面寫(xiě)兩個(gè)函數(shù)是一樣的,這個(gè)寫(xiě)法的好處是當(dāng)代碼出現(xiàn)了錯(cuò)誤的時(shí)候,不會(huì)阻斷程序的執(zhí)行,而是進(jìn)入catach方法。
all方法的使用Promise對(duì)象上的方法,實(shí)例不能使用,只能這個(gè)對(duì)象使用,這個(gè)方法通過(guò)了并行執(zhí)行異步操作的能力,并且在所有的異步操作完成后才執(zhí)行回調(diào)
Promise .all([runAsync1(),runAsync2(),runAsync3()]) .then(function(results){ console.log(results); });
Promise.all來(lái)執(zhí)行前面的三個(gè)異步的函數(shù),all()接收一個(gè)數(shù)組參數(shù),里面的執(zhí)行最終都返回Promise對(duì)象,只有等三個(gè)異步操作都執(zhí)行完成后才會(huì)進(jìn)入到then里面,all會(huì)把所有的異步操作的結(jié)果放在一個(gè)數(shù)組中傳給then,就是上面的results,代碼的輸出結(jié)果:
有了all,可以并行執(zhí)行多個(gè)異步操作,并且在一個(gè)回調(diào)中處理所有的返回?cái)?shù)據(jù),一個(gè)常用的場(chǎng)景:游戲類(lèi)的素材比較多的應(yīng)用,打開(kāi)網(wǎng)頁(yè)的時(shí)候,預(yù)先加載需要用到的各種資源,如圖片,flash以及各種靜態(tài)文件,等到所有都加載完成,我們?cè)龠M(jìn)行頁(yè)面的初始化。
race的用法這個(gè)也是Promise類(lèi)上面的私有方法,對(duì)于前面的all方法來(lái)說(shuō)是:誰(shuí)的程序執(zhí)行的慢,就等誰(shuí)執(zhí)行完才回調(diào)。但是對(duì)于race來(lái)說(shuō):誰(shuí)的程序執(zhí)行的快,就以它為標(biāo)準(zhǔn)調(diào)用回調(diào)函數(shù),其用法基本上是一樣的,把上面runAsync1函數(shù)的延遲改為1秒
Promise .race([runAsync1(),runAsync2(),runAsync3()]) .then(function(results){ console.log(results); });
這三個(gè) 異步操作同樣是并行執(zhí)行的,但是等到1秒后,runAsync1已經(jīng)執(zhí)行完畢,于是then接受到了執(zhí)行完畢的回調(diào),輸出回調(diào)結(jié)果;與此同時(shí),runAsyn2和runAsyn3也繼續(xù)執(zhí)行,輸出了執(zhí)行的結(jié)果,但是不能回調(diào)then方法。
這個(gè)方法的使用場(chǎng)景很多,比如可以用race給某個(gè)異步請(qǐng)求設(shè)置超時(shí)時(shí)間,并且在超時(shí)后執(zhí)行相應(yīng)的操作:
// 請(qǐng)求某個(gè)圖片資源 異步 function requestImg(){ var p=new Promise(function(resolve,reject){ var img=new Image(); // 創(chuàng)建一個(gè)圖片對(duì)象實(shí)例 Image后面沒(méi)有參數(shù)的時(shí)候,括號(hào)可以省略 img.src="xxxxx"; // 給對(duì)象上面的屬性設(shè)置屬性值 img.onload=function(){ resolve(img); // 圖片成功加載的時(shí)候,把img對(duì)象作為參數(shù)傳到回調(diào)函數(shù)里面 } }); return p; // 當(dāng)調(diào)用這個(gè)函數(shù)的時(shí)候可以使用then方法 } // 延時(shí)函數(shù) 給請(qǐng)求計(jì)時(shí) function timeout(){ var p=new Promise(function(resolve,reject){ setTimeout(function(){ reject("圖片請(qǐng)求超時(shí)"); },4000); }); return p; } Promise.race([requsetImg(),timeout()]) .then(function(results){ console.log(results); // 圖片成功加載會(huì)把圖片的路徑打印在控制臺(tái) }) .catch(function(reason){ console.log(reason); // 失敗會(huì)提示加載失敗 })
requestImg函數(shù)會(huì)異步請(qǐng)求一張圖片,圖片地址寫(xiě)錯(cuò),肯定是無(wú)法加載圖片請(qǐng)求。timeout函數(shù)是一個(gè)延時(shí)4秒的異步操作,把這兩個(gè)返回Promise對(duì)象的函數(shù)放到race里面,如果4秒內(nèi)圖片請(qǐng)求成功,就會(huì)回調(diào)then方法,執(zhí)行正常的流程,否則進(jìn)入catch方法,顯示圖片請(qǐng)求超時(shí)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95098.html
摘要:回調(diào)函數(shù)是的一大特色官方的基本都是以會(huì)回調(diào)方式傳遞函數(shù)返回值。針對(duì)這種普遍問(wèn)題,應(yīng)勢(shì)而生基本用法創(chuàng)建做一些異步操作的事情,然后一切正常的構(gòu)造器接受一個(gè)函數(shù)作為參數(shù),它會(huì)傳遞給這個(gè)回調(diào)函數(shù)兩個(gè)變量和。 Promise 是什么? Promise 對(duì)象用來(lái)進(jìn)行延遲(deferred) 和 異步(asynchronous) 計(jì)算。 一個(gè) Promise 處于以下三種狀態(tài)之一: pend...
摘要:是一個(gè)注冊(cè)在指定源和路徑下的事件驅(qū)動(dòng)??梢蕴峁┯行в行У碾x線(xiàn)體驗(yàn),攔截網(wǎng)絡(luò)請(qǐng)求。出于安全原因,要求必須在下才能運(yùn)行。返回一個(gè)對(duì)象,的結(jié)果是對(duì)象值對(duì)象組成的數(shù)組。當(dāng)事件的處理程序執(zhí)行完畢后,可以認(rèn)為安裝完成了。 在前端越來(lái)越重的這個(gè)時(shí)代,頁(yè)面加載速度成為了一個(gè)重要的指標(biāo)。對(duì)于這個(gè)問(wèn)題,業(yè)界也有一些解決方案。 瀏覽器緩存、協(xié)議緩存、強(qiáng)緩存 懶加載(首屏) CDN 多域名突破下載并發(fā)限制。...
摘要:是一個(gè)注冊(cè)在指定源和路徑下的事件驅(qū)動(dòng)??梢蕴峁┯行в行У碾x線(xiàn)體驗(yàn),攔截網(wǎng)絡(luò)請(qǐng)求。出于安全原因,要求必須在下才能運(yùn)行。返回一個(gè)對(duì)象,的結(jié)果是對(duì)象值對(duì)象組成的數(shù)組。當(dāng)事件的處理程序執(zhí)行完畢后,可以認(rèn)為安裝完成了。 在前端越來(lái)越重的這個(gè)時(shí)代,頁(yè)面加載速度成為了一個(gè)重要的指標(biāo)。對(duì)于這個(gè)問(wèn)題,業(yè)界也有一些解決方案。 瀏覽器緩存、協(xié)議緩存、強(qiáng)緩存 懶加載(首屏) CDN 多域名突破下載并發(fā)限制。...
摘要:后來(lái)在爬取不到讓我一度懷疑人生的時(shí)候巧合下,發(fā)現(xiàn)磁力鏈接有小寫(xiě)字母,有長(zhǎng)度的,有長(zhǎng)度的。。 原文博客: 羞羞的node爬蟲(chóng) 前言 學(xué)了一陣子node,除了用 express 寫(xiě)東西,就沒(méi)怎么做過(guò)東西突然就想寫(xiě)個(gè) 爬蟲(chóng) 來(lái)玩一玩,而且還是爬一些羞羞的東西 使用模塊 SuperAgent 是個(gè) http 方面的庫(kù),可以發(fā)起 get 或 post 請(qǐng)求。 cheerio 大家可以理解成一個(gè) ...
閱讀 2953·2023-04-25 19:20
閱讀 815·2021-11-24 09:38
閱讀 2067·2021-09-26 09:55
閱讀 2444·2021-09-02 15:11
閱讀 2076·2019-08-30 15:55
閱讀 3622·2019-08-30 15:54
閱讀 3159·2019-08-30 14:03
閱讀 2973·2019-08-29 17:11