摘要:上代碼異步執(zhí)行成功的構造函數(shù)接收一個函數(shù)參數(shù),并傳入兩個參數(shù),分別表示異步操作執(zhí)行成功后的回調函數(shù)和異步操作執(zhí)行失敗后的回調函數(shù)。第一個回調函數(shù)是對象的狀態(tài)變?yōu)闀r調用,第二個回調函數(shù)是對象的狀態(tài)變?yōu)闀r調用。
這篇文章只解決三個問題。
什么是promise?
promise有什么用?
promise怎么用?
1.什么是promise?
對于ES6來說,就是一個構造函數(shù),可以用new Promise( )來創(chuàng)建Promise實例。
2.promise有什么用?
先想象兩個場景:
一,業(yè)務中,需要請求后臺的兩個接口,但是需要第一個返回成功結果之后再請求第二個接口,這是可能會寫成下面這個樣子,
var request = function(){ var xhr1 = new XMLHttpRequest(); xhr1.onreadystatechange = function(){ if(xhr1.readyState !== 4){ alert("第一步請求失敗了,請重試!"); return; } if(xhr1.status === 200){ console.log("第一步請求成功了,我們開始下一步吧!"); var xhr2 = new XMLHttpRequest(); xhr2.open("GET", url); xhr2.onreadystatechange = function(){ if(xhr2.readyState !== 4){ alert("第二步請求失敗了,請重試!"); return; } if(xhr2.status === 200){ //兩次請求成功后做的一些事情.... } else { alert("第二步請求失敗了,請重試!"); } }; xhr2.responseType = "json"; xhr2.setRequestHeader("Accept", "application/json2"); xhr2.send(); } else { alert("第一步請求失敗了,請重試!"); } }; xhr1.responseType = "json"; xhr1.setRequestHeader("Accept", "application/json1"); xhr1.send(); }); } request();
上面代碼用xhr對象實現(xiàn)了兩次異步請求,代碼很長。不過這僅僅是兩層回調嵌套,想象一下更多的異步回調依賴有多可怕…
二,我們都知道,nodejs的一大特點就是事件驅動,那就肯定要利用事件的回調函數(shù)來處理邏輯,多層的回調嵌套也就在所難免。那么你的代碼很可能就會寫成這個德行,
async(1,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,final); }); }); }); }); }); }); }); })
就此你掉進了又長又丑的嵌套地獄。
咋辦?
用promise(回答了“promise是干啥的”)。
咋用?
往下看。
3.promise 怎么用?
在學習怎么使用Promise的同時,需要不時接觸幾個關于它的知識點。能理解最好,理解不了用著用著就理解了。
首先需要了解的是每個Promise實例都有三種狀態(tài):
1.進行中狀態(tài) pending
2.成功狀態(tài) resolved
3.失敗狀態(tài) rejected
同一時間下Promise實例只能有一種狀態(tài),且只能改變一次,改完之后就再也不能變了。
變化的途徑只有兩種,第一,從pending變?yōu)閞esolved;第二,從pending變?yōu)閞ejected。
接下來就一步步的完成一個promise的使用。
第一步,new一個Promise實例。上代碼:
var promise = new Promise(function(resolve,reject){ if(/*異步執(zhí)行成功*/){ resolve(value) } else { reject(error) } });
Promise的構造函數(shù)接收一個函數(shù)參數(shù),并傳入兩個參數(shù)resolve,reject分別表示異步操作執(zhí)行成功后的回調函數(shù)和異步操作執(zhí)行失敗后的回調函數(shù)。執(zhí)行resolve(),會將當前promise對象的狀態(tài)更改為resolved,執(zhí)行reject()會將當前promise對象的狀態(tài)更改為rejected。
這時一個Promise對象已經(jīng)創(chuàng)建完成,異步腳本的結果也已經(jīng)被存在這個Promise對象中了,但它是成功是失敗?我們怎么讀取呢?
第二步,then方法。接著上代碼:
var promise = new Promise(function(resolve,reject){ if(/*異步執(zhí)行成功*/){ resolve(value); } else { reject(error); } }); promise.then(function(value){ console.log(value); },function(error){ console.log(error); })
每個Promise實例都有一個then方法,它就是處理Promise中存儲的異步執(zhí)行結果的方法。then方法可以接受兩個回調函數(shù)作為參數(shù)。第一個回調函數(shù)是Promise對象的狀態(tài)變?yōu)镽esolved時調用,第二個回調函數(shù)是Promise對象的狀態(tài)變?yōu)镽eject時調用。其中,第二個函數(shù)是可選的,不一定要提供。這兩個函數(shù)都接受Promise對象傳出的值作為參數(shù)。
需要特別注意的是then方法的返回值還是一個Promise!這就意味著then方法是支持鏈式調用的。
第三步,catch方法。
catch方法等同于then(null,function(){}),也就是用來處理rejected狀態(tài)下Promise數(shù)據(jù)的。關于catch個人認為記住兩點就好。第一,用catch來處理rejected的Promise;第二,用catch來捕獲之前所有鏈式調用中拋出的Error對象,注意是所有,包括Promise構造函數(shù)、then方法、鏈式調用的then方法、以及之前的catch,這些步驟拋出的錯誤都可以被catch捕獲。
var promise = new Promise(function(resolve,reject){ if(false){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); }) .catch(function(reason){ console.log(error); })
上面代碼會輸出reject(error)傳入的error值,也就是catch的第一種用法。
var promise = new Promise(function(resolve,reject){ if(true){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); console.log(x); }) .catch(function(reason){ console.log(reason); })
上面代碼會將Promise的狀態(tài)改為resolved,并執(zhí)行then方法,在then方法中會拋出一個x變量未定義的錯誤,并由catch方法捕獲到并打印出來,這就是catch的第二個用法。
至此實際上我們已經(jīng)學會了Promise的基礎應用。接下來再學習兩個比較好用的方法。
第一個,Promise.all方法。
該方法能夠并行運行異步方法,并在結果都返回之后進行統(tǒng)一處理,并返回一個新的Promise對象。
var p = Promise.all([p1, p2, p3]);
上面代碼中,Promise.all方法接受一個“數(shù)組”作為參數(shù),p1、p2、p3都是Promise對象的實例。
p的狀態(tài)由p1、p2、p3決定,分成兩種情況。
(1)只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled,此時p1、p2、p3的返回值組成一個數(shù)組,傳遞給p的回調函數(shù)。(fulfilled可以理解為resolved)
(2)只要p1、p2、p3之中有一個被rejected,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數(shù)。
var p = Promise.all([p1,p2,p3]); p.then(function(results){ console.log(results) });
當打開網(wǎng)頁時,需要預先加載各種資源如圖片、flash以及各種靜態(tài)文件,所有的都加載完后,我們再進行頁面的初始化。這種場景是很適合使用Promise.all的。
第二個,Promise.race方法。
與all方法類似,同樣是能夠并行運行異步方法,并在結果都返回之后進行統(tǒng)一處理,并返回一個新的Promise對象。
var p = Promise.race([p1,p2,p3]);
上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數(shù),也就是說誰執(zhí)行的快就返回誰的。
race方法可以添加請求超時的限制。
//請求某個圖片資源 function requestImg(){ var p = new Promise(function(resolve, reject){ var img = new Image(); img.onload = function(){ resolve(img); } img.src = "xxxxxx"; }); return p; } //延時函數(shù),用于給請求計時 function timeout(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ reject("圖片請求超時"); }, 5000); }); return p; } Promise .race([requestImg(), timeout()]) .then(function(results){ console.log(results); }) .catch(function(reason){ console.log(reason); });
到這,關于Promise的三個問題已經(jīng)解答完了,希望能夠為大家學習Promise提供一點幫助。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82256.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網(wǎng)絡基礎知識之 HTTP 協(xié)議 詳細介紹 HTT...
摘要:意味著操作成功完成。當調用方法的時候會設置一個狀態(tài),調用方法的時候會設置一個狀態(tài)。返回是自定義的,狀態(tài)由自己設但不能不給狀態(tài),不然不會執(zhí)行下一個鏈詳細文檔文檔 背景:在一個方法中處理一個復雜的異步操作時會涉及到多個異步處理,它們可能是層層嵌套導致這個方法異常的龐大,影響日后的代碼維護和問題的查找 解決:在ES6中提供了一個Promise的對象,它以一種鏈式的寫法將異步操作邏輯與異步返...
摘要:首先是一個構造器函數(shù),使用它必須通過一個實例出來,并且出來的實例暈有一個內置的參數(shù),這個參數(shù)是一個函數(shù),這個參數(shù)擁有自己內置的兩個參數(shù),和,并且這兩個參數(shù)也是兩個函數(shù)異步操作成功上面這個就是一個最簡單的對象屬于的一個方法,里面的兩個參數(shù)屬于 首先promise是一個構造器函數(shù),使用它必須通過new一個實例出來,并且new出來的實例暈有一個內置的參數(shù),這個參數(shù)是一個函數(shù),這個參數(shù)擁有自己...
摘要:首先是一個構造器函數(shù),使用它必須通過一個實例出來,并且出來的實例暈有一個內置的參數(shù),這個參數(shù)是一個函數(shù),這個參數(shù)擁有自己內置的兩個參數(shù),和,并且這兩個參數(shù)也是兩個函數(shù)異步操作成功上面這個就是一個最簡單的對象屬于的一個方法,里面的兩個參數(shù)屬于 首先promise是一個構造器函數(shù),使用它必須通過new一個實例出來,并且new出來的實例暈有一個內置的參數(shù),這個參數(shù)是一個函數(shù),這個參數(shù)擁有自己...
摘要:源碼學習本篇為上一篇源碼學習的補充,主要是來介紹和方法。那個率先改變的實例的返回值,就傳遞給的回調函數(shù)。基本介紹可見阮一峰老師的書籍。的狀態(tài)由決定,分成兩種情況。只有的狀態(tài)都變成,的狀態(tài)才會變成,此時的返回值組成一個數(shù)組,傳遞給的回調函數(shù)。 Promise源碼學習(2) 本篇為上一篇源碼學習(1)的補充,主要是來介紹Promise.all()和Promise.race()方法。閑話少敘...
閱讀 1684·2021-11-23 09:51
閱讀 3174·2021-09-26 10:21
閱讀 798·2021-09-09 09:32
閱讀 881·2019-08-29 16:06
閱讀 3308·2019-08-26 13:36
閱讀 772·2019-08-26 10:56
閱讀 2564·2019-08-26 10:44
閱讀 1143·2019-08-23 14:04