十分鐘快速瞭解 ES6 Promise

什麼是Promise

Promise最早由社區提出並實現,典型的一些庫有Q,when, bluebird等;它們的出現是為了更好地解決JavaScript中異步編程的問題,傳統的異步編程最大的特點就是地獄般的回調嵌套,一旦嵌套次數過多,就很容易使我們的代碼難以理解和維護。而Promise則可以讓我們通過鏈式調用的方法去解決回調嵌套的問題,使我們的代碼更容易理解和維護,而且Promise還增加了許多有用的特性,讓我們處理異步編程得心應手。


如何創建Promise

ES6給我們提供了一個原生的構造函數Promise,我們可以看一下這個構造函數:

十分鐘快速瞭解 ES6 Promise

下面我們先來創建一個promise,下面是一個簡單的示例:

十分鐘快速瞭解 ES6 Promise

下面來解釋一下上面的代碼:

【1】因為Promise是一個構造函數,所以我們使用了new操作符來創建promise。

【2】構造函數Promise的參數是一個函數(暫時叫它func),這個函數(func)有兩個參數resolve和reject,它們分別是兩個函數,這兩個函數的作用就是將promise的狀態從pending(等待)轉換為resolved(已解決)或者從pending(等待)轉換為rejected(已失敗)。

【3】創建後的promise有一些方法,then和catch。當然我們也可以人為的在Promise函數上添加一些滿足我們自己需求的方法,方便每一個promise對象使用。

如果我們使用一些ES6的語法的話,我們上面的代碼會更加簡潔:

十分鐘快速瞭解 ES6 Promise

其實可以這樣理解,Promise函數體的內部包裹著一個異步的請求或者操作或者函數;然後我們可以在這個異步的操作完成的時候使用resolve函數將我們獲得的結果傳遞出去,或者使用reject函數將錯誤的消息傳遞出去。


Promise對象的一些方法

Promise對象可以通過使用then方法將上一步返回的結果獲取過來(不管是resolved還是rejected),可以通過使用catch方法捕獲Promise對象在使用catch之前的異常。

首先來說一下then方法的使用:

十分鐘快速瞭解 ES6 Promise

我們可以看到,then方法可以接受兩個函數作為參數,第一個函數是用來處理resolve的結果,第二個是可選的,用來處理reject的結果。也就是說,我們在創建p這個Promise對象的時候,通過函數resolve傳遞出去的結果可以被p的第一個then方法中的第一個函數捕獲然後作為它的參數。通過函數reject傳遞出去的結果可以被p的第一個then方法中的第二個函數捕獲然後作為它的參數。

當然我們還可以在每一個then方法中創建新的Promise,然後將這個Promise對象返回,之後我們就可以在後面的then方法中繼續對這個對象進行操作。下面是一個簡單的例子:

十分鐘快速瞭解 ES6 Promise

從上面的代碼中我們可以看到,一旦創建一個Promise對象之後,我們就可以使用then方法來進行鏈式的調用,而且我們可以把每一次的結果都返還給下一個then方法,然後在下一個then方法中對這個值進行處理。每一個then方法中都可以再次新創建一個Promise對象,然後返還給下一個then方法處理。

Promise還有另一個方法catch,這個方法其實是then方法的一種特例,這個特例就是:

.then(null, rejection)

相當於我們不使用then方法的第一個函數,只是用第二個函數;catch函數比較簡單,就是用來捕獲之前的then方法裡面的異常,我們可以簡單的來看一個例子:

十分鐘快速瞭解 ES6 Promise

上面代碼的輸出結果如下:

progress...
VM141:9 Error: fail(…)

我們可以使用catch函數來捕獲整個then函數鏈中的異常。


Promise的一些方法

Promise.all方法用來包裝許多個Promise實例,然後組成了一個新的Promise對象,新的Promise對象的狀態由前面幾個被包裹的Promise對象的狀態決定,如果前面的Promise都被resolve了,那麼新的Promise的狀態也是resolve的;只要有一個Promise被reject了,那麼組成的新的Promise的狀態也是reject的。

可以看下面一個例子:

十分鐘快速瞭解 ES6 Promise

上面的代碼的輸出結果如下:

[ Promise { <pending> },
Promise { <pending> },
Promise { <pending> } ]
[ 1, 2, 3 ] // 3s後輸出的結果
/<pending>/<pending>/<pending>

Promise.race方法和上面的Promise.all有點類似,都是包裝許多的Promise對象,然後組成了一個新的Promise對象,但是使用Promise.race的含義是:只要包裹的的Promise對象中有一個的狀態發生了改變,那麼組成的這個新的Promise對象的狀態就是上面那個率先改變的Promise實例的狀態。

下面是一個簡單的例子:

十分鐘快速瞭解 ES6 Promise

上面程序的輸出結果如下:

[ Promise { <pending> },
Promise { <pending> },
Promise { <pending> } ]
1 // 是最先改變狀態的那個Promise實例resolve的值
/<pending>/<pending>/<pending>

Promise.resolve方法主要是將一個值轉變為一個Promise對象,然後使它具有Promise的一些方法和特性,為了滿足我們一些特殊情況下的要求。

下面是一個簡單的例子:

十分鐘快速瞭解 ES6 Promise

上面的輸出結果如下:

[ null, 0, 'hello', { then: [Function: then] } ]
a thenable obj // Promise.resolve方法會將具有then方法的對象轉換為一個Promise對象,然後就立即執行then方法。

Promise.reject方法和Promise.resolve方法一樣,只不過通過Promise.reject方法產生的Promise對象的狀態是rejected的,下面是一個示例:

let p = Promise.reject('fail');
p.catch((err) => {
console.log(err);
}); // fail

上面的內容把ES6中新增的Promise的基本使用方法給大家講了一下,希望對大家有多幫助。


分享到:


相關文章: