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