談談ES6中Promise的使用

Promise是一個對象,同時也是一個構造函數,爲了對Promise有一個直觀的認識,首先咱們把Promise直接在控制檯打印出來:
Promise
經過這張圖片咱們能夠很清除地看到,Promise本身身上有all,race,resolve,reject這些咱們熟悉的方法,而在原型之上,則有then,catch,finally這些一樣很熟悉的方法。javascript

Promise怎麼用?

既然Promise是一個構造函數,那咱們就new一個實例出來吧:java

var p = new Promise(function(resolve,reject){
    setTimeout(() =>{
        if(1){    //假設操做成功
            console.log("執行成功")
            resolve("執行成功以後的數據")
        }else{
            console.log("執行失敗")
            reject("執行失敗以後的數據")
        }
    }, 1000)
})

Promise接收一個參數,是一個函數,該函數有兩個參數:resolve和reject,也是兩個函數,這兩個函數是javascript引擎給咱們提供的,不用咱們本身去部署。
Promise有三種狀態:pending/fulfilled/rejected 。pending就是未決,fulfilled能夠理解爲成功,rejected能夠理解爲失敗。數組

resolve函數的做用是將Promise的狀態置爲fullfiled,當狀態變成fullfiled時,then方法的第一個回調會執行,reject函數是將Promise的狀態置爲rejected,當狀態變成rejected時,then方法的第二個回調或者catch方法裏的回調會執行異步

而且Promise有如下特色:
1 .對象的狀態不受外界影響,只有內部異步操做的結果能夠修改他的狀態,任何其餘操做都沒法修改他的狀態。
2 .一旦狀態發生改變,就不會再變,任什麼時候候均可以獲得這個結果。若是改變已經發生了,只要添加回調函數,任什麼時候候均可以獲得返回值。函數

運行以上代碼,咱們在控制檯能夠看到打印出了執行成功:
運行結果
注意,這裏咱們只是new了一個Promise對象,並無去調用它,裏面代碼就已經執行了,因此咱們通常都是把Promise放到一個函數裏面,在須要的時候調用,爲了方便探討,咱們對函數作以下封裝:spa

function createPro(num,time){
    return new Promise(function(resolve,reject){
        setTimeout(() =>{
            if(num > 5){
                console.log("執行成功")
                resolve("執行成功以後的數據")
            }else{
                console.log("執行失敗")
                reject("執行失敗以後的數據")
            }
        }, time)
    })
}

咱們封裝了一個函數,返回一個Promise對象,咱們給該函數傳遞兩個參數,num和time,num用來控制異步操做的結果,num大於5理解爲執行成功,time用來控制延遲時間。
剛纔咱們看到函數已經執行成功,可是resolve和reject傳遞的參數去哪裏了?還記得剛纔咱們說過當Promise狀態改變時會執行then或者catch方法裏的回調吧,沒錯,在回調函數裏面就能夠取到傳遞的數據。code

then方法和catch方法

then中有2個參數,第一個參數是狀態變爲成功後應該執行的回調函數,第二個參數是狀態變爲失敗後應該執行的回調函數。對象

createPro(10,1000).then((data)=>{
    console.log("num爲10時then方法的第一個參數收到的:"+data)
},(err)=>{
    console.log("num爲10時then方法的第二個參數收到的:"+err)
})
createPro(1,1000).then((data)=>{
    console.log("num爲1時then方法的第一個參數收到的:"+data)
},(err)=>{
    console.log("num爲1時then方法的第二個參數收到的:"+err)
})

執行以上函數,咱們觀察控制檯的打印狀況:
執行結果blog

因爲第一次調用createPro時,咱們給num傳的值爲10,比5要大,因此在函數內部執行了resolve方法,Promise的狀態變成了fullfiled,then方法的第一個回調被執行,而且接收到了resolve方法傳遞來的數據,而在第二次調用createPro時,咱們給num傳的值爲1,比5要小,因此在函數內部調用了reject方法,Promise的狀態變成了rejected,then方法的第二個回調被執行,而且收到了reject傳遞的數據。
固然then方法也能夠只接收一個回調,即異步操做成功時執行的回調。
catch方法是用來接收異步操做失敗的結果,效果和then方法的第二個參數同樣:接口

createPro(1,1000).then((data)=>{
    console.log("then方法的第一個參數收到的:",data)
}).catch((err)=>{
    console.log("catch方法裏收到的:",err)
})

咱們在控制檯能夠看到打印了:
執行結果

若是咱們想要無論成功仍是失敗,都要執行一些操做能夠用Promise.finally(),可是該方法的回調函數不接受任何參數,這意味着沒有辦法知道,前面的 Promise 狀態究竟是fulfilled仍是rejected。這代表,finally方法裏面的操做,是與狀態無關的,不依賴於 Promise 的執行結果。

Promise的鏈式操做

Promise的then方法以後會繼續返回一個Promise對象,能夠繼續調用then方法,而接收的參數值就是上一個then方法return的結果:

createPro(10,1000).then((data)=>{
    console.log("then方法的第一個參數收到的:"+data)
    return 100
}).then(data=>{
    console.log("第二個then方法接收到的的參數",data)
})

執行結果
咱們能夠看到在第二個then中接收到了咱們在第一個then方法中返回的數字100.固然咱們也能夠返回一個Promise對象

createPro(10,1000).then((data)=>{
    console.log("第一個then:",data)
    return createPro(10,1000)
}).then(data=>{
    console.log("第二個then:",data)
    return createPro(2,1000)
}).then(data=>{
    console.log("第三個then:",data)
    return createPro(10,1000)
}).catch(err=>{
    console.log("公共的catch方法:",err)
})

運行結果以下:
執行結果

咱們能夠看到函數依次執行,因此Promise能夠解決所謂「地獄回調」的問題,而且若是中途有異步操做執行失敗,都會執行catch裏面的回調。

Promise.all和Promise.race

Promise的all方法提供了並行執行異步操做的能力,而且在全部異步操做執行完後才執行回調。Promise.all接收一個數組參數,裏面的異步操做的並行執行的,等到它們都執行完後纔會進到then裏面。那麼,異步操做返回的數據哪裏去了呢?都在then裏面呢,all會把全部異步操做的結果放進一個數組中傳給then。
咱們對createPro函數設置不一樣的延遲時間:

Promise.all([createPro(10,1000),createPro(10,2000),createPro(10,3000)]).then(data=>{
    console.log(data)
})

執行以上代碼,咱們能夠看到控制檯每隔一秒打印出了一次「執行成功」,而且在最後打印出了傳遞的數據,是一個數組:
執行結果
Promise.all有一個常常用到的場景就是,在一個頁面有多個請求接口,當全部接口都請求到數據以後,關閉loading遮罩層,這時候咱們就能夠用到Promise.all方法。

理解了Promise.all再來看Promise.race就好理解多了,all方法的效果其實是「誰跑的慢,以誰爲準執行回調」,那麼相對的就有另外一個方法「誰跑的快,以誰爲準執行回調」,這就是Promise.race:

Promise.race([createPro(10,1000),createPro(10,2000),createPro(10,3000)]).then(data=>{
    console.log(data)
})

運行結果以下:
執行結果
咱們在控制檯能夠看到,一秒以後打印出了「執行成功」,而且拿到了resolve傳遞的數據,可是另外兩個函數並無中止運行,因此咱們看到每間隔一秒又打印出了「執行成功」。

關於Promise經常使用的方法先寫這些了,另外還有Promise.resolve和Promise.reject等方法有時間再研究,因爲做者水平有限,文章不免有錯誤之處,還請大神斧正。

相關文章
相關標籤/搜索