1顾孽、什么要使用Promise?
1)指定回調(diào)函數(shù)的方式更加靈活秒赤。原來需要在啟動異步任務(wù)之前就需指定回調(diào)函數(shù)址晕;Promise啟動異步任務(wù)致讥,會返回一個promise對象仅仆,我們只需給promise對象綁定回調(diào)函數(shù)器赞。
2)支持鏈?zhǔn)秸{(diào)用垢袱,可以解決回調(diào)地獄問題。回調(diào)地獄是指回調(diào)函數(shù)嵌套調(diào)用港柜,外部回調(diào)函數(shù)異步執(zhí)行的結(jié)果是嵌套回調(diào)函數(shù)執(zhí)行的條件请契。不便于閱讀和異常處理咳榜。Promise可以支持鏈?zhǔn)秸{(diào)用解決回調(diào)地獄問題。也可以使用async爽锥、await涌韩。
2、Promise的API使用
1)Pormise構(gòu)造函數(shù):Promise(executor){}
????? a. executor函數(shù):執(zhí)行器(resolve, reject)=>{}
????? b. resolve函數(shù):內(nèi)部定義成功時我們調(diào)用的函數(shù)value=>{}
????? c. reject函數(shù):內(nèi)部定義失敗時我們調(diào)用的函數(shù)reason=>{}
????? 注意:executor會在Promise內(nèi)部立即同步調(diào)用氯夷,異步操作在執(zhí)行器中執(zhí)行臣樱。
2)Promise.prototype.then方法:(onResolved, onRejected)=>{}
????? a. onResolved函數(shù):成功的回調(diào)函數(shù)(value)=>{}
????? b. onRejected函數(shù):失敗的回調(diào)函數(shù)(reason)=>{}
????? 注意:無論是成功的回調(diào)還是失敗的回調(diào)返回的是一個新的Promise對象。
3)Promise.prototype.catch方法:(onRejected)=>{}
????? onRejected函數(shù):失敗的回調(diào)函數(shù)(reason)=>{}
4)Promise.resolve方法:(value)=>{}
????? value是成功的數(shù)據(jù)或Promise對象腮考。
5)Promise.reject方法:(reason)=>{}
????? reason是失敗的原因雇毫。
6)Promise.all方法:(promises)=>{}
promises是一個包含n個promise的數(shù)組。返回的是一個新的Promise踩蔚,只有所有promise都成功才成功棚放,只要有一個失敗則直接失敗。
7)Promise.allSettled()方法:(promises)=>{}
接受一組 Promise 實例作為參數(shù)馅闽,包裝成一個新的 Promise 實例飘蚯。只有等到所有這些參數(shù)實例都返回結(jié)果,不管是fulfilled還是rejected福也,包裝實例才會結(jié)束局骤。
該方法返回的新的 Promise 實例,一旦結(jié)束拟杉,狀態(tài)總是fulfilled庄涡,不會變成rejected。狀態(tài)變成fulfilled后搬设,Promise 的監(jiān)聽函數(shù)接收到的參數(shù)是一個數(shù)組穴店,每個成員對應(yīng)一個傳入Promise.allSettled()的 Promise 實例。
8)Promise.race()方法:(promises)=>{}
promises是一個包含n個promise的數(shù)組拿穴。返回的是一個新的Promise泣洞,第一個完成的promise的結(jié)果狀態(tài)為最終的結(jié)構(gòu)狀態(tài)。要么成功默色,要么是失敗球凰。
9)Promise.any()方法:(promises)=>{}
該方法接受一組 Promise 實例作為參數(shù),包裝成一個新的 Promise 實例返回腿宰。只要參數(shù)實例有一個變成fulfilled狀態(tài)呕诉,包裝實例就會變成fulfilled狀態(tài);如果所有參數(shù)實例都變成rejected狀態(tài)吃度,包裝實例就會變成rejected狀態(tài)甩挫。
Promise.any()跟Promise.race()方法很像,只有一點不同椿每,就是Promise.any()不會因為某個 Promise 變成rejected狀態(tài)而結(jié)束伊者,必須等到所有參數(shù) Promise 變成rejected狀態(tài)才會結(jié)束英遭。
3、Promise 的幾個關(guān)鍵問題
1)Promise狀態(tài)改變的方式
????? a. resolve(value)方法:pending狀態(tài)變?yōu)閞esolved亦渗。
????? b. reject(reason)方法: pending狀態(tài)變?yōu)閞ejected狀態(tài)挖诸。
????? c. 拋異常:pending狀態(tài)變?yōu)閞ejected。
2)改變 promise 狀態(tài)和指定回調(diào)函數(shù)先后順序問題
????? 回答是都有可能, 正常情況下是先指定回調(diào)再改變狀態(tài), 但也可以先改狀態(tài)再指定回調(diào)法精。
????? a. 如何先改狀態(tài)再指定回調(diào)?
????????? ① 在執(zhí)行器中直接調(diào)用 resolve()/reject()多律;
????????? ② 延遲更長時間才調(diào)用 then()。
????? b. 什么時候才能得到數(shù)據(jù)?
????????? ① 如果先指定的回調(diào), 那當(dāng)狀態(tài)發(fā)生改變時, 回調(diào)函數(shù)就會調(diào)用, 得到數(shù)據(jù)搂蜓;
????????? ② 如果先改變的狀態(tài), 那當(dāng)指定回調(diào)時, 回調(diào)函數(shù)就會調(diào)用, 得到數(shù)據(jù)菱涤。
3)promise 異常傳透問題
???? a. 當(dāng)使用 promise 的 then 鏈?zhǔn)秸{(diào)用時, 可以在最后指定失敗的回調(diào)。
???? b. 前面任何操作出了異常, 都會傳到最后失敗的回調(diào)中處理洛勉。
4粘秆、使用Promise進(jìn)行順序(sequence)處理
1)使用async函數(shù)配合await或者使用generator函數(shù)配合yield。
2)使用promise.then通過for循環(huán)或者Array.prototype.reduce實現(xiàn)收毫。
promise = promise.then(task).then(pushValue);的代碼就是通過不斷對promise進(jìn)行處理攻走,不斷的覆蓋promise變量的值,以達(dá)到對promise對象的累積處理效果此再。但是這種方法需要promise這個臨時變量
有時候我們使用Promise.all()執(zhí)行很多個網(wǎng)絡(luò)請求昔搂,可能有一個請求出錯,但我們并不希望其他的網(wǎng)絡(luò)請求也返回reject输拇,要錯都錯摘符,這樣顯然是不合理的。如何做才能做到promise.all中即使一個promise程序reject策吠,promise.all依然能把其他數(shù)據(jù)正確返回呢逛裤?