開篇首先設想一個平常開發經常會遇到的需求:在多個接口異步請求數據,而後利用這些數據來進行一系列的操做。通常會這樣去寫:jquery
|
這樣的寫法的原理是,當執行一些異步操做時,咱們須要知道操做是否已經完成,全部當執行完成的時候會返回一個回調函數,表示操做已經完成。es6
使用回調函數的形式理解起來並不困難,可是實際的應用當中會有如下的缺點:ajax
爲了解決上述的問題,Promise 對象應運而生,在 EMCAScript 2015 當中已經成爲標準。api
一個 Promise 對象能夠理解爲一次將要執行的操做(經常被用於異步操做),使用了 Promise 對象以後能夠用一種鏈式調用的方式來組織代碼,讓代碼更加直觀。並且因爲 Promise.all
這樣的方法存在,可讓同時執行多個操做變得簡單。接下來就來簡單介紹 Promise 對象。數組
首先來看一段使用了 Promise 對象的代碼。promise
|
jsFiddle(請用現代瀏覽器打開)瀏覽器
上面的代碼實現的功能很是簡單,helloWord
函數接受一個參數,若是爲 true
就打印 「Hello World!」,若是爲 false
就打印錯誤的信息。helloWord
函數返回的是一個 Promise 對象。babel
在 Promise 對象當中有兩個重要方法————resolve
和 reject
。異步
resolve
方法可使 Promise 對象的狀態改變成成功,同時傳遞一個參數用於後續成功後的操做,在這個例子當中就是 Hello World! 字符串。函數
reject
方法則是將 Promise 對象的狀態改變爲失敗,同時將錯誤的信息傳遞到後續錯誤處理的操做。
上面提到了 resolve
和 reject
能夠改變 Promise 對象的狀態,那麼它究竟有哪些狀態呢?
Promise 對象有三種狀態:
helloWorld 的例子中的 then
方法就是根據 Promise 對象的狀態來肯定執行的操做,resolve 時執行第一個函數(onFulfilled),reject 時執行第二個函數(onRejected)。
helloWorld 的例子當中利用了 then(onFulfilld, onRejected)
方法來執行一個任務打印 「Hello World!」,在多個任務的狀況下 then
方法一樣能夠用一個清晰的方式完成。
|
上述例子經過鏈式調用的方式,按順序打印出了相應的內容。then
可使用鏈式調用的寫法緣由在於,每一次執行該方法時老是會返回一個 Promise 對象。另外,在 then
onFulfilled 的函數當中的返回值,能夠做爲後續操做的參數,所以上面的例子也能夠寫成:
|
一樣能夠打印出正確的內容。
catch
方法是 then(onFulfilled, onRejected)
方法當中 onRejected
函數的一個簡單的寫法,也就是說能夠寫成 then(fn).catch(fn)
,至關於 then(fn).then(null, fn)
。使用 catch
的寫法比通常的寫法更加清晰明確。
Promise.all
能夠接收一個元素爲 Promise 對象的數組做爲參數,當這個數組裏面全部的 Promise 對象都變爲 resolve 時,該方法纔會返回。
|
上面的例子模擬了傳輸兩個數據須要不一樣的時長,雖然 p2 的速度比 p1 要快,可是 Promise.all
方法會按照數組裏面的順序將結果返回。
平常開發中常常會遇到這樣的需求,在不一樣的接口請求數據而後拼合成本身所需的數據,一般這些接口之間沒有關聯(例如不須要前一個接口的數據做爲後一個接口的參數),這個時候 Promise.all
方法就能夠派上用場了。
還有一個和 Promise.all
相相似的方法 Promise.race
,它一樣接收一個數組,不一樣的是隻要該數組中的 Promise 對象的狀態發生變化(不管是 resolve 仍是 reject)該方法都會返回。
最後是關於 Promise 對象的兼容性問題。
在瀏覽器端,一些主流的瀏覽器都已經可使用 Promise 對象進行開發,在 Node.js 配合 babel 也能夠很方便地使用。
若是要兼容舊的瀏覽器,建議能夠尋找一些第三方的解決方案,例如 jQuery 的 $.Deferred。
感謝你的閱讀,有不足之處請爲我指出。
詳細參考:http://es6.ruanyifeng.com/#docs/promise