Promise学习笔记
一、異步任務的處理
這里我從一個實際的例子來作為切入點:
- 我們調用一個函數,這個函數中發送網絡請求(我們可以用定時器來模擬);
- 如果發送網絡請求成功了,那么告知調用者發送成功,并且將相關數據返回過去;
- 如果發送網絡請求失敗了,那么告知調用者發送失敗,并且告知錯誤信息;
二、什么是Promise呢?
在上面的解決方案中,我們確實可以解決請求函數得到結果之后,獲取到對應的回調,但是它存在兩個主要的問題:
- 第一,我們需要自己來設計回調函數、回調函數的名稱、回調函數的使用等;
- 第二,對于不同的人、不同的框架設計出來的方案是不同的,那么我們必須耐心去看別人的源碼或者文檔,以便可以理解它這個函數到底怎么用;
我們來看一下Promise的API是怎么樣的:
- Promise是一個類,可以翻譯成 承諾、許諾 、期約;
- 當我們需要給予調用者一個承諾:待會兒我會給你回調數據時,就可以創建一個Promise的對象;
- 在通過new創建Promise對象時,我們需要傳入一個回調函數,我們稱之為executor
這個回調函數會被立即執行,并且給傳入另外兩個回調函數resolve、reject;
當我們調用resolve回調函數時,會執行Promise對象的then方法傳入的回調函數;
當我們調用reject回調函數時,會執行Promise對象的catch方法傳入的回調函數;
三、Promise的代碼結構
上面Promise使用過程,我們可以將它劃分成三個狀態:
- 待定(pending): 初始狀態,既沒有被兌現,也沒有被拒絕;
當執行executor中的代碼時,處于該狀態; - 已兌現(fulfilled): 意味著操作成功完成;
執行了resolve時,處于該狀態; - 已拒絕(rejected): 意味著操作失敗;
執行了reject時,處于該狀態;
四、Promise重構請求
那么有了Promise,我們就可以將之前的代碼進行重構了:
五、Executor
Executor是在創建Promise時需要傳入的一個回調函數,這個回調函數會被立即執行,并且傳入兩個參數:
通常我們會在Executor中確定我們的Promise狀態:
- 通過resolve,可以兌現(fulfilled)Promise的狀態,我們也可以稱之為已決議(resolved);
- 通過reject,可以拒絕(reject)Promise的狀態;
這里需要注意:一旦狀態被確定下來,Promise的狀態會被 鎖死,該Promise的狀態是不可更改的
- 在我們調用resolve的時候,如果resolve傳入的值本身不是一個Promise,那么會將該Promise的狀態變成兌現(fulfilled);
- 在之后我們去調用reject時,已經不會有任何的響應了:
六、resolve不同值的區別
-
情況一:如果resolve傳入一個普通的值或者對象,那么這個值會作為then回調的參數;
-
情況二:如果resolve中傳入的是另外一個Promise,那么這個新Promise會決定原Promise的狀態:
-
情況三:如果resolve中傳入的是一個對象,并且這個對象有實現then方法,那么會執行該then方法,并且根據then方法的結果來決定Promise的狀態:
七、Promise的實例方法——then方法
7.1 一個Promise的then方法是可以被多次調用的:
- 每次調用我們都可以傳入對應的fulfilled(成功的)回調;
- 當Promise的狀態變成fulfilled的時候,這些(成功的)回調函數都會被執行;
7.2 then方法可以接受兩個參數
then方法是Promise對象上的一個方法:它其實是放在Promise的原型上的 Promise.prototype.then
then方法接受兩個參數:
- fulfilled的回調函數:當狀態變成fulfilled時會回調的函數;
- reject的回調函數:當狀態變成reject時會回調的函數;
7.3 then方法的返回值
then方法本身是有返回值的,它的返回值是一個Promise,所以我們可以進行如下的鏈式調用:
- 但是then方法返回的Promise到底處于什么樣的狀態呢? Promise有三種狀態,那么這個Promise處于什么狀態呢?
- 當then方法中的回調函數本身在執行的時候,那么它處于pending狀態;
- 當then方法中的回調函數返回一個結果時,那么它處于fulfilled狀態,并且會將結果作為resolve的參數;
情況一:返回一個普通的值;
情況二:返回一個Promise;
情況三:返回一個thenable值;
- 當then方法拋出一個異常時,那么它處于reject狀態;
九、Promise的實例方法——catch方法
9.1 catch方法可以多次調用
catch方法也是Promise對象上的一個方法:它也是放在Promise的原型上的 Promise.prototype.catch
一個Promise的catch方法是可以被多次調用的:
- 每次調用我們都可以傳入對應的reject回調;
- 當Promise的狀態變成reject的時候,這些回調函數都會被執行;
9.2 catch方法的返回值
事實上catch方法也是會返回一個Promise對象的,所以catch方法后面我們可以繼續調用then方法或者catch方法:
下面的代碼,后續是catch中的err result打印,還是then中的res result打印呢?
答案:res result打印,這是因為catch傳入的回調在執行完后,默認狀態依然會是fulfilled的,因為是fulfilled狀態,所以會執行then里面的回調函數;
如果我們希望后續繼續執行catch,那么需要拋出一個異常:
十、Promise的實例方法——finally方法
finally是在ES9(ES2018)中新增的一個特性:表示無論Promise對象無論變成fulfilled還是reject狀態,最終都會被執行的代碼。
finally方法是不接收參數的,因為無論前面是fulfilled狀態,還是reject狀態,它都會執行。
十一、Promise的類方法——resolve方法
前面我們學習的then、catch、finally方法都屬于Promise的實例方法,都是存放在Promise的prototype上的。
下面我們再來學習一下Promise的類方法:
有時候我們已經有一個現成的內容了,希望將其轉成Promise來使用,這個時候我們可以使用 Promise.resolve 方法來完成。
- Promise.resolve的用法相當于new Promise,并且執行resolve操作:
resolve參數的形態:
-
情況一:參數是一個普通的值或者對象
-
情況二:參數本身是Promise
-
情況三:參數是一個thenable
十二、Promise的類方法——reject方法
reject方法類似于resolve方法,只是會將Promise對象的狀態設置為reject狀態。
Promise.reject的用法相當于new Promise,只是會調用reject:
注意:Promise.reject傳入的參數無論是什么形態,都會直接作為reject狀態的參數傳遞到catch的。
十三、Promise的類方法——all方法
另外一個類方法是Promise.all:
- 它的作用是將多個Promise包裹在一起形成一個新的Promise;
- 新的Promise狀態由包裹的所有Promise共同決定:
當所有的Promise狀態變成fulfilled狀態時,新的Promise狀態為fulfilled,并且會將所有Promise的返回值 組成一個數組; 當有一個Promise狀態為reject時,新的Promise狀態為reject,并且會將第一個reject的返回值作為參數;
all方法有一個缺陷:
當有其中一個Promise變成reject狀態時,新Promise就會立即變成對應的reject狀態。 那么對于resolved的,以及依然處于pending狀態的Promise,我們是獲取不到對應的結果的;
十四、Promise的類方法——allSettled方法
在ES11(ES2020)中,添加了新的API Promise.allSettled:
- 該方法會在所有的Promise都有結果(settled),無論是fulfilled,還是reject時,才會有最終的狀態;
- 并且這個Promise的結果一定是fulfilled的;
我們來看一下打印的結果: - allSettled的結果是一個數組,數組中存放著每一個Promise的結果,并且是對應一個對象的;
- 這個對象中包含status狀態,以及對應的value值;
十五、Promise的類方法——race方法
如果有一個Promise有了結果,我們就希望決定最終新Promise的狀態,那么可以使用race方法:
- race是競技、競賽的意思,表示多個Promise相互競爭,誰先有結果,那么就使用誰的結果;
十六、Promise的類方法——any方法
any方法是ES12中新增的方法,和race方法是類似的:
- any方法會等到一個fulfilled狀態,才會決定新Promise的狀態;
- 如果所有的Promise都是reject的,那么也會等到所有的Promise都變成rejected狀態;
如果所有的Promise都是reject的,那么會報一個AggregateError的錯誤:
總結:
總結
以上是生活随笔為你收集整理的Promise学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文阅读 - Video Swin Tr
- 下一篇: 好用的记事本_分类记事本软件哪个好用?大