這里是一個重點大綱, promise的知識點比較復雜, 主要參考阮一峰的es6入門,具體知識點那里有非常完美的解釋。
promise通俗來講就是一個容器, 里面保存著某個未來才會結束的時事件(通常是一個一步操作)。
- promise一共有三種狀態:pending,fullfilled,rejected。只有異步操作的結果可以決定pending最終的走向,結局只有一個,非fullfilled 即rejected,一旦狀態改變,再也不會更改, 正是promise的含義。
resolved 并不是其中的一種狀態,resolved 代指兩種結局,fullfilled和rejected,但是習慣將成功的結果叫做resolved。 - 缺點???
promise 一旦開始立即執行無法取消
如果不設置回調函數,會吃掉錯誤,不會拋出
pending時無法知道進度以及走向 - promise構造函數接受兩個參數,是兩個回調函數,成功的和失敗的。
promise實例生成后,可以用then()方法分別指定resolved 和rejected的回調函數。then()函數可以面條式調用,注意,在promise 內部, 總是先執行同步任務,(此處應該和微任務隊列時間循環有關系,別處再議) - 優秀的做法:
一般來說,調用resolve 或者reject之后promise的任務就完成 了,有別的邏輯應該寫在then()里面,而不應該寫在resolve或reject后面,所以最好在resolve或者reject前面加return。做完我該做的啥也不管了。 - then方法返回的也是個promise,所以可以鏈式調用,前一個回調函數完成以后,會將結果作為參數傳入下一個then函數,then方法要等到前一個promise狀態發生變化才會被調用!
- 箭頭函數在這用
- promise.prototype.catch
promise的錯誤拋出非常重要,如果沒有使用catch指定錯誤出來的回調函數,promise的對象拋出的錯誤不會傳遞到外層代碼,不會結束進程種植腳本的執行,即不會有任何反應。還會從錯誤地方繼續執行下去。
promise.prototype.catch方法是.then(null,rejection)或.then(undefined,rejection)的別名,用于指定發生錯誤時的回調函數。
具體寫法很重要去文章里找。
promise的錯誤具有冒泡性質,會一直向后傳遞, 直到遇到catch語句被捕獲。 - 優秀的做法:
then()函數不寫rejected回調,直接調用catch方法捕獲錯誤。因為catch能捕獲到前面的錯誤,并且更像同步寫法。catch方法返回的還是一個promise,可以繼續.then()。 - 科普:Node
node 有一個unhandledRejection事件,專門監聽未捕獲的rejection錯誤,可以在監聽函數里面拋出錯誤,
process.on('unhandledRejection',function(err,promise){
throw err;
})
此函數接收兩個參數,一個錯誤對象, 另一個是報錯的promise對象,用來定位報錯環境,node計劃要廢除此事件。
- promise.prototype.finally()
finally方法用于指定不管promise對象最后狀態如何,都會執行的操作。(比如關閉服務器)該方法是ES2018引入標準的。
他不接受任何參數。屬于then()的特例。
promise
.then(result=>{})
.catch(err=>{})
.finally(()=>{})
- promise.all()(與門)
用于將多個promise實例包裝成一個promise實例
const p = Promise.all([p1,p2,p3]);
p的狀態取決于參數數組(可以不必是數組,有iterator接口就行,參數值不是promise 對象也可以,會先調用Promise.resolve進行轉換),全都fulfilled的情況下, p的狀態才會fulfilled,否則就是rejected。
p的返回值?
(1)fulfilled 情況下,參數組的返回值組成一個數組,傳遞給p的回調函數;
(2)rejected情況下,第一個被rejected的實例的返回值,會傳遞給p的回調函數。
- Promise.race
只要有一個實例的狀態發生改變,p的狀態就跟著改變。那個率先改變的Promise的返回值就傳遞給p的回調函數。 - Promise.resolve()
將現有對象轉換成promise 對象。
!在本輪事件循環末尾執行,而不是下一輪事件循環開頭!
可以轉換的分為三種情況:promise對象,thenable對象,沒有then方法或根本不是對象。
此處的應用:如果象牙立即得到一個promise 對象,比較方便的方法就是直接調用promise.resolve方法。 - Promise.reject()
返回一個新的Promise實例,該實例的狀態為rejected - Promise.try()
實際開發中,經常遇到一種情況:不知道或者不想區分函數是同步還是異步,就想用then制定下一步,用catch捕獲錯誤:
Promise.resolve().then(f)
因為promise.then().catch()的catch只能捕獲異步的錯誤,那么同步也會報錯怎么辦,事實上,Promise.try()就是模擬try catch代碼塊,將同步異步全都捕獲。
Promise.try(()=>{}.then().catch())