1.前言前端
在平時的業務開發中,前端一般須要請求後臺獲取數據,或者NodeJs讀取文件等等一系列的異步操做,咱們一般須要利用異步操做的結果或者對異步操做的結果進行處理。一般咱們的解決方案是:在異步操做成功或者失敗的回調函數裏面寫方法,在異步操做比較簡單的時候這樣寫代碼仍是比較好理解的,當業務逐漸趨於複雜,這就造成了回調地獄,代碼嵌套層數太多而且難以理解。不過,辦法老是有的,可使用ES6的新特性Promise來解決問題。es6
2.Promise的定義編程
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。json
所謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。從語法上說,Promise 是一個對象,從它能夠獲取異步操做的消息。Promise 提供統一的 API,各類異步操做均可以用一樣的方法進行處理。promise
Promise對象有如下兩個特色。app
(1)對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。ecmascript
(2)一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從pending變爲fulfilled和從pending變爲rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱爲 resolved(已定型)。若是改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。異步
有了Promise對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象提供統一的接口,使得控制異步操做更加容易。ide
Promise也有一些缺點。首先,沒法取消Promise,一旦新建它就會當即執行,沒法中途取消。其次,若是不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。第三,當處於pending狀態時,沒法得知目前進展到哪個階段(剛剛開始仍是即將完成)。異步編程
3.基本用法
ES6規定,Promise對象是一個構造函數,用來生成Promise實例
代碼以下:
const promise=new Promise(function(resolve,reject){ if(/* 異步操做成功*/){ resolve(value) }else{ reject(error); } });
Promise構造函數接受一個函數做爲參數,改函數的兩個參數分別是resolve與reject,resolve函數的做用是:將Promsie對象的狀態從「未完成」變爲「成功」,在異步操做成功時回調,並將異步操做的結果value做爲參數傳遞出去;reject函數的做用是:Promise對象的狀態由「未完成」變爲「失敗」,在異步操做失敗時調用,並將異步操做報出的錯誤做爲參數傳遞出去。
Promise實例生成之後,能夠用then方法分別制定resolved的狀態和reject狀態的回調函數。
代碼以下:
promise.then(function(value) { // success }, function(error) { // failure });
4.小例子-封裝Ajax操做
const getJSON = function(url) { const promise = new Promise(function(resolve, reject){ const handler = function() { if (this.readyState !== 4) { return; } if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; const client = new XMLHttpRequest(); client.open("GET", url); client.onreadystatechange = handler; client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); }); return promise; }; getJSON("./js/package.json").then(function(json) { console.log('Contents: ' , json); }, function(error) { console.error('出錯了', error); });
以上的代碼是經過用原生的Ajax和Promise實現的獲取json的一個方法,在網頁中運行得出如下的結果:
5.reject狀態回調方法的寫法
promise .then(function(data) { // success }, function(err) { // error });
以上是咱們的reject狀態方法,能夠做爲promsie對象then方法的第二個參數。不過這樣寫有個缺點是:若是在resolve狀態以後再拋出錯誤,則不會捕獲。
推薦寫法:
// 推薦寫法 promise .then(function(data) { //cb // success }) .catch(function(err) { // error });
經過Promise這種寫法,咱們使不少異步操做的方法寫法同步化,可以更好的組織優化代碼,並且在捕獲錯誤也更加容易,方便咱們調試解決問題。不足之處,多多指正。
參考資料: