promise對象

一、特色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

相關文章
相關標籤/搜索