promise 拙見

一,promise是什麼?

promise 是最先由社區提出和實現是一種解決異步編程的方案,比其餘傳統的解決方案(回調函數和事件)更合理和強大。編程

ES6 將其寫進了語言標準,統一了用法,原生提供了 promise 對象。數組

ES6 規定,promise對象是一個構造函數,用來生成 promise 實例。promise

二,promise是爲解決什麼問題而產生的?

promise是爲解決異步處理回調金字塔問題而產生的緩存

三,promise的兩個特色

1,promise對象的狀態不受外界影響異步

a,pending 初始狀態異步編程

b,fulfilled 成功狀態函數

c,rejected 失敗狀態this

promise 有以上三種狀態,只有一步操做的結果能夠解決當前是哪種狀態,其餘任何操做都沒法改變這種狀態;spa

2,promise 的狀態一旦改變,就不會再變,任什麼時候候均可以獲得這個結果,狀態不能夠逆,只能由pending 變成fulfilled 或者pending 變成 rejectedprototype

四,promise的三個缺點

1,沒法取消promise,一旦新建它就會當即執行,沒法中途取消

2,若是不設置回調函數,promise 內部拋出的錯誤,不會反映到外部

3,當處於 pending 狀態時,沒法得知目前進展到了哪個階段,是剛剛開始仍是即將完成

五,promise在哪存放成功回調序列和失敗回調序列?

1,onResolvedCallbacks 成功後要執行的回調序列 是一個數組

2,onResolvedCallbacks 失敗後要執行的回調序列 是一個數組

以上兩個數組存放在promise  建立實例時給promise這個類傳的函數中,默認都是空數組。

每次實例 then 的時候 傳入onFulfilled 成功回調 onRejected 失敗回調,若是此時的狀態是pending 則將onFulfilled 和 onRejected push 到對應的成功回調序列數組和失敗回調序列數組中,若是此時的狀態是fulfilled 則 onFulfilled 當即執行,若是此時的狀態是rejected 則 onRejected 當即執行

上述序列中的回調函數執行的時候 是有順序的,即按照順序依次執行

六,promise的用法

1,promise 構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve 和 reject。它們是兩個函數,由JavaScript 引擎提供,不用本身部署。

const promise = new Promise(function(resolve, reject) {
      // ... some code

      if (/* 異步操做成功 */){
        resolve(value);
      } else {
        reject(error);
      }
  });

2,resolve函數的做用是,將Promise對象的狀態從「未完成」變爲「成功」(即從 pending 變爲 resolved),在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去;reject函數的做用是,將Promise對象的狀態從「未完成」變爲「失敗」(即從 pending 變爲 rejected),在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。

3,Promise實例生成之後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數。

    promise.then(function(value) {
      // success
    }, function(error) {
      // failure
    });

then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise對象的狀態變爲resolved時調用,第二個回調函數是Promise對象的狀態變爲rejected時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise對象傳出的值做爲參數。

7、按照Promise A+規範寫Promise的簡單實現原理

// 第一步:Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve和reject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。
    function Promise(task) {

        let that = this; // 緩存this
        that.status = 'pending'; // 進行中的狀態
        that.value = undefined; //初始值

        that.onResolvedCallbacks = []; // 存放成功後要執行的回調函數的序列
        that.RejectedCallbacks = []; // 存放失敗後要執行的回調函數的序列
        // 該方法是將Promise由pending變成fulfilled
        function resolve (value) {
            if (that.status == 'pending') {
                that.status = 'fulfilled';
                that.value = value;
                that.onResolvedCallbacks.forEach(cb => cd(that.value))
            }

        }
        // 該方法是將Promise由pending變成rejected
        function reject (reason) {
          if (that.status == 'pending') {
                that.status = 'rejected';
                that.value = reason;
                that.onRjectedCallbacks.forEach(cb => cd(that.value))
            }
        }

        try {
        // 每個Promise在new一個實例的時候 接受的函數都是當即執行的
            task(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }

// 第二部 寫then方法,接收兩個函數onFulfilled onRejected,狀態是成功態的時候調用onFulfilled 傳入成功後的值,失敗態的時候執行onRejected,傳入失敗的緣由,pending 狀態時將成功和失敗後的這兩個方法緩存到對應的數組中,當成功或失敗後 依次再執行調用
    Promise.prototype.then = function(onFulfilled, onRejected) {
        let that = this;
        if (that.status == 'fulfilled') {
            onFulfilled(that.value);
        }
        if (that.status == 'rejected') {
            onRejected(that.value);
        }
        if (that.status == 'pending') {
            that.onResolvedCallbacks.push(onFulfilled);
            that.onRjectedCallbacks.push(onRejected);
        }
    }

8、Promise 鏈式寫法

咱們先來看一個例子,根據例子得出結論,而後再寫源碼的實現部分來驗證結論

    let promise = new Promise(function (resolve, reject) {
        resolve(100);// reject(100)
    });

    promise.then(function (data) {
        return data+100;

    },function (err) {
       return 'ssss';

    }).then(function (data) {
        console.log(data);// 200  // undefined // sss
    })

從上面的例子能夠看出:

當第一個promise的成功的回調裏返回 200時,第二個promise的成功回調的參數就是200,當將resolve(100)改爲reject(100)的時候,由於失敗回調中什麼也沒有返回因此第二個promise的成功回調中的參數是undefined,當失敗的回調中返回sss時,第二個promise的成功回調中的參數是sss,由此咱們能夠看出,第一個promise無論成功回調仍是失敗回調,他的返回值做爲第二個promise中的成功時回調函數的參數值,鏈式寫法能一直then下去的緣由:鏈式調用靠的是返回新的promise,來保證能夠一直走成功或失敗

9、 Promise.catch

Promise.prototype.catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。

    //catch原理就是隻傳失敗的回調
    Promise.prototype.catch = function(onRejected){
        this.then(null,onRejected);
    }

 

10、 Promise.all 方法

參數:接受一個數組,數組內都是Promise實例

返回值:返回一個Promise實例,這個Promise實例的狀態轉移取決於參數的Promise實例的狀態變化。當參數中全部的實例都處於resolve狀態時,返回的Promise實例會變爲resolve狀態。若是參數中任意一個實例處於reject狀態,返回的Promise實例變爲reject狀態

  Promise.all = function(promises){
     return new Promise(function(resolve,reject){
       let done = gen(promises.length,resolve);
       for(let i=0;i<promises.length;i++){
         promises[i].then(function(data){
           done(i,data);
         },reject);
       }
     });
    }

 

11、Promise.resolve

返回一個Promise實例,這個實例處於resolve狀態。

根據傳入的參數不一樣有不一樣的功能:

值(對象、數組、字符串等):做爲resolve傳遞出去的值

Promise實例:原封不動返回

    //返回一個馬上成功的promise
    //別人提供 給你一個方法,須要你傳入一個promise,但你只有一個普通的值,你就能夠經過這個方法把這個普通的值(string number object)轉成一個promise對象
    Promise.resolve = function(value){
      return new Promise(function(resolve){
        resolve(value);
      });
    }

 

12、 Promise.reject

返回一個Promise實例,這個實例處於reject狀態。

參數通常就是拋出的錯誤信息。

 //返回一個馬上失敗的promise
    Promise.reject = function(reason){
      return new Promise(function(resolve,reject){
        reject(reason);
      });
    }

 

十3、 Promise.race

參數:接受一個數組,數組內都是Promise實例

返回值:返回一個Promise實例,這個Promise實例的狀態轉移取決於參數的Promise實例的狀態變化。當參數中任何一個實例處於resolve狀態時,返回的Promise實例會變爲resolve狀態。若是參數中任意一個實例處於reject狀態,返回的Promise實例變爲reject狀態。

    Promise.race = function(promises){
      return new Promise(function(resolve,reject){
        for(let i=0;i<promises.length;i++){
          promises[i].then(resolve,reject);
        }
      });
    }
相關文章
相關標籤/搜索