Promise在英語裏有但願、承諾之意,在Javascript,它是異步解決方案。有人質疑已經有了更高級異步解決方案async/await
,還有必要了解promise
?是的,由於大部分項目異步方案使用promise
,除此以外,promise
也是實現async/await
的基礎。最重要的,promise
還是前端面試熱點。
前端
Promise:統一異步操做方法控制器
es6
若是你看到標題便閱讀本文,想必已經瞭解promise
基礎知識!面試
阮老師課程有句話,「爲了行文方便,本章後面的
resolved
統一隻指fulfilled
狀態」,說明resolved並不必定是表明完成。
數組
//終於排到隊了....
function bookDinner(msg) {
return new Promise((resolve, reject) => {
resolve(msg)
}).then(msg => console.log("完成訂單:", msg))
.catch(msg => console.log("訂單異常:", msg))
}複製代碼
上例爲舉例排隊訂餐場景,排隊過程當中狀態是pending
。排到你後,收銀臺收銀並給你一個號牌,須要等待取餐,這個時候狀態即是resolved
,收銀臺僅僅給了你一個訂餐成功的承諾,人家比必定保證你能吃上。一旦發生異常或者其餘事件,仍可能致使訂單失敗。promise
bookDinner(Promise.reject("廚師帶着老闆娘跑了!"))//'訂單異常: 廚師帶着老闆娘跑了!'複製代碼
resolved
不能表明fullfilled
!
bash
上例中咱們使用Promise
構造函數建立promise
實例,並賦予了實例不能改變的狀態。在執行任務中咱們使用到了catch
方法,用於指定狀態爲rejected
或發生錯誤的回調函數。異步
catch
方法是then(null,rejection)
或者then(undefined,rejection)
的別名,那爲何會有
catch
方法?async
try/catch
方法,代碼易讀;catch
能夠捕捉到前面promise
對象(then
方法也是promise
對象)的錯誤;let p = new Promise((resolve, reject) => {
resolve()
})
//第一種:
p.then(() => { throw new Error('rejected') })
.catch(v => console.log(v)) // "Error: rejected"
//第二種:
p.then(() => { throw new Error('rejected') }, v => console.log(v)) //報錯複製代碼
catch
方法只能捕獲其前的錯誤;let p = new Promise((resolve, reject) => {
resolve()
})
p.catch(err => console.log(err))
.then(() => { throw new Error('catch後的報錯') })//報錯獲取不到複製代碼
catch
方法報錯能夠在下一個catch
方法獲取,由於catch
是then
的變形。let p = new Promise((resolve, reject) => {
reject()
})
p.catch(() => { throw new Error('catch後的報錯') })
.catch(err => console.log(err)) //'Error: catch後的報錯'複製代碼
Promise
對象拋出的錯誤不會傳遞到外層代碼,即不會影響其餘任務正常執行,通俗的說法就是「Promise
會吃掉錯誤」。函數
console.log('start....')
let p = new Promise((resolve, reject) => {
console.log('promise')
throw new Error("是否會影響其餘代碼?")
})
p.then(v => console.log(v))
console.log('end!')
// start....
// promise
// end!
//報錯:Uncaught (in promise) Error: 是否會影響其餘代碼?複製代碼
promise.all([])
:數組內全部promise
實例狀態均爲fullfilled
,數組promise
容器才爲fullfilled
。數組只要有一個狀態rejected
,數組promise容器狀態九尾rejected。
post
這個方法確實挺有意思,仍是以我們點餐爲例,食物和勺子都得具有才完成吃飯的任務,吃飯狀態才能是fullfilled
。任何一項不知足的話,對於吃飯任務來講,狀態即是rejected
。
//得到食物
function getFood() {
return Promise.resolve("蓋飯")
}
//得到勺子
function getSpoon() {
return Promise.resolve('勺子')
}
//吃飯
function eatFood() {
return Promise.all([getFood(), getSpoon()])
}
eatFood().then(v => console.log('吃飯:',v))//'吃飯:["蓋飯", "勺子"]'
.catch(err => console.log(err)) 複製代碼
若是做爲參數的
Promise
實例,本身定義了catch
方法,那麼它一旦被rejected
,並不會觸發Promise.all()
的catch
方法。
上邊的例子咱們稍加改變,服務員遲遲不給你拿勺子,這個時候,針對getSpoon這個任務報了個錯,服務員立馬知道了,拿來勺子,讓你完成吃飯任務。實際上是catch方法返回了一個新的實例。
//得到食物
function getFood() {
return Promise.resolve("蓋飯")
}
//得到勺子
function getSpoon() {
return Promise.reject('還沒給勺子')
}
let getSpoonAgin = getSpoon().then(v => v).catch(err => console.log(err))
//吃飯
function eatFood() {
return Promise.all([getFood(), getSpoonAgin])
}
eatFood().then(v => console.log("吃飯:", v)) //'吃飯:["蓋飯", undefined]'
.catch(err => console.log("未能吃飯:", err))
}複製代碼
promise.race:與promise.all相似,參數也是promise實例數組。哪一個promise實例優先"到達",promise.race容器的狀態就是先到達的promise實例狀態。
繼續點餐的例子,你們工做比較忙,中午只能等待15分鐘,爲了吃上飯你點了兩份飯,畢竟胃容量有限,只能哪份先來就吃哪份(槓精們,不要擡槓哈!)固然此處只是舉了兩個任務狀態都是fullfilled
的例子。
function getFood1() {
return Promise.resolve("蓋飯")
}
function getFood2() {
return Promise.resolve('餃子')
}
function eatFood() {
return Promise.race([getFood1(), getFood2()])
}
eatFood().then(v => console.log("吃飯:", v)) //'吃飯: 蓋飯'
.catch(err => console.log("未能吃飯:", err))複製代碼
以上只是針對Promise
運行方式以及部分方法進行說明,在項目實戰中Promise
的使用遠比上邊所說的例子複雜,但願本篇對於您理解promise
異步解決方案有所幫助。
具體在使用中細節能夠學習阮一峯老師ES6課程。
若是想要了解任務執行順序的,可閱讀聊聊前端面試之輸出順序
謝謝您的閱讀,請多指教!