一、特色es6
A、對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。json
B、一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果。若是改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。數組
二、基本用法promise
ES6規定:Promise對象是一個構造函數,用來生成Promise實例。異步
console.dir(Promise)async
var promise = new Promise(function(resolve, reject) { // ... some code if (/* 異步操做成功 */){ resolve(value); } else { reject(error); } }); promise.then(function(value){ console.log('成功!'); },function(error){ console.log('失敗!'); })
Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve和reject。它們是兩個函數,由JavaScript引擎提供,不用本身部署。函數
resolve函數的做用是,將Promise對象的狀態從「未完成」變爲「成功」(即從Pending變爲Resolved),在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去;reject函數的做用是,將Promise對象的狀態從「未完成」變爲「失敗」(即從Pending變爲Rejected),在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。post
Promise實例生成之後,能夠用then方法分別指定Resolved狀態和Reject狀態的回調函數。this
then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise對象的狀態變爲Resolved時調用,第二個回調函數是Promise對象的狀態變爲Reject時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise對象傳出的值做爲參數。spa
三、Promist.prototype.then()
a、Promise實例的方法;
b、做用:爲Promise實例添加狀態改變時的回調函數;
c、參數:第一個參數是Resolved狀態的回調函數,第二個參數(可選)是Rejected狀態的回調函數;
d、返回值:返回一個新的Promise實例(不是原來的那個),所以能夠進行鏈式操做。
getJSON("/posts.json").then(function(json) { return json.post; }).then(function(post) { // ... });
依次指定了兩個回調函數。第一個回調函數完成之後,會將返回結果做爲參數,傳入第二個回調函數。
四、Promise.prototype.catch()
a、Promise實例的方法,是.then(null, rejection)
的別名;
b、做用:指定發生錯誤時的回調函數
getJSON('/posts.json').then(function(posts) { // ... }).catch(function(error) { // 處理 getJSON 和 前一個回調函數運行時發生的錯誤 console.log('發生錯誤!', error); });
getJSON
方法返回一個 Promise 對象,若是該對象狀態變爲Resolved
,則會調用then
方法指定的回調函數;若是異步操做拋出錯誤,狀態就會變爲Rejected
,就會調用catch
方法指定的回調函數,處理這個錯誤。另外,then
方法指定的回調函數,若是運行中拋出錯誤,也會被catch
方法捕獲。
五、Promise.all()
a、做用:降多個promise的實例,包裝成一個新的Promise實例;
var p = Promise.all([p1, p2, p3]);
b、參數:接收一個數組做爲參數,數組的每一個成員都是一個Promise對象的實例,若是不是Promise對象的實例,將調用Promise.resolve方法,將參數轉爲Promise實例,再進一步處理;
c、注意:Promise.all() 方法的參數能夠不是數組,但必須具備Iterator接口,且返回的每一個成員都是Promise實例;
d、p的狀態由p1,p2,p3決定
只有p一、p二、p3的狀態都變成fulfilled,p的狀態纔會變成fulfilled,此時p一、p二、p3的返回值組成一個數組,傳遞給p的回調函數;
只要p一、p二、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。
// 生成一個Promise對象的數組 var promises = [2, 3, 5, 7, 11, 13].map(function (id) { return getJSON("/post/" + id + ".json"); }); Promise.all(promises).then(function (posts) { // ... }).catch(function(reason){ // ... });
//
promises是包含6個Promise實例的數組,只有這6個實例的狀態都變成fulfilled,或者其中有一個變爲rejected,纔會調用Promise.all方法後面的回調函數。
六、Promise.race()
a、將多個Promise實例,包裝成一個新的Promise實例。
var p = Promise.race([p1, p2, p3]);
只要p一、p二、p3之中有一個實例率先改變狀態,p的狀態就跟着改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。
Promise.race方法的參數與Promise.all方法同樣,若是不是 Promise 實例,就會先調用下面講到的Promise.resolve方法,將參數轉爲 Promise 實例,再進一步處理。
七、Promise.resolve()
a、做用:將對象轉換成Promise對象
b、參數:
(1)、參數是一個Promise實例,則原封不動的返回這個Promise實例;
(2)、參數是一個thenable對象,Promise.resolve方法將這個對象轉換成Promise對象,而後當即執行thenable對象的then方法;
let thenable = { then: function(resolve, reject) { resolve(42); } };
(3)、參數不是具備then方法的對象,或者根本就不是對象,則返回一個新的Promise對象,狀態爲resolved,因此回調函數會當即執行。注意:Promise.resolve方法的參數,會同時傳遞給回調函數。
(4)、不帶任何參數:直接返回一個resolved狀態的Promise對象。注意:當即resolved的Promise對象,是在本輪「事件循環」的結束時,而不是下一輪「事件循環」開始時。
setTimeout(function () { console.log('three'); }, 0); Promise.resolve().then(function () { console.log('two'); }); console.log('one'); // one // two // three
setTimeout(fn,0)是在下一輪事件循環時開始執行;
Promise.resolve()是在本輪事件循環結束執行;
console.log('one')是當即執行。
八、Promise.reject()
做用:返回一個新的Promise實例,狀態爲rejected,所以回調函數會當即執行。
九、done()
Promise對象的回調鏈,不論是then仍是catch方法結尾,要是最後一個方法拋出錯誤,都有可能沒法捕捉到。所以提供一個done方法,處於回調鏈的最底端,保證拋出的任何錯誤會被捕捉到,而且拋向全局。
done方法的使用能夠像then那樣,提供resolved和rejected狀態的回調函數。
asyncFunc() .then(f1) .catch(r1) .then(f2) .done(); //實現 Promise.prototype.done = function (onFulfilled, onRejected) { this.then(onFulfilled, onRejected) .catch(function (reason) { // 拋出一個全局錯誤 setTimeout(() => { throw reason }, 0); }); };
十、finally()
finally方法無論Promise狀態是什麼,都會執行的操做。接受一個普通的函數做爲回調函數,這個函數必定會執行。
參考:http://es6.ruanyifeng.com/#docs/promise