Promise,我是這麼理解的!

1、promise不是承諾

Promise在英語裏有但願、承諾之意,在Javascript,它是異步解決方案。有人質疑已經有了更高級異步解決方案async/await,還有必要了解promise?是的,由於大部分項目異步方案使用promise,除此以外,promise也是實現async/await的基礎。最重要的,promise還是前端面試熱點。
前端

Promise:統一異步操做方法控制器
es6

2、大話promise

若是你看到標題便閱讀本文,想必已經瞭解promise基礎知識!面試

一、resolve不是完成

阮老師課程有句話,「爲了行文方便,本章後面的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

二、但願用不到的catch

上例中咱們使用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方法獲取,由於catchthen的變形。
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.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.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))複製代碼

3、寫在最後

以上只是針對Promise運行方式以及部分方法進行說明,在項目實戰中Promise的使用遠比上邊所說的例子複雜,但願本篇對於您理解promise異步解決方案有所幫助。

具體在使用中細節能夠學習阮一峯老師ES6課程。

若是想要了解任務執行順序的,可閱讀聊聊前端面試之輸出順序

謝謝您的閱讀,請多指教!

相關文章
相關標籤/搜索