promise原理探究

前言

Promise是個什麼玩意,你們都知道,度娘告訴我,以同步方式書寫異步,解決回調地獄。。。git

狀態機

早聞Promise的大名,簡單介紹,根據狀態改變來執行相應處理函數。
Promise的狀態極其簡單,只有 "pending", "resolved", "rejected"三種狀態
而後就是如何實現的問題,最關鍵的固然是監聽到狀態的更新,而後才能作出迴應,那麼如何知道狀態變了呢?
最初單純的我開了一個腦洞,有如下想法:github

  • 寫一個定時器不斷查詢狀態值,若是有變化,那麼執行回調
  • 利用ES5的 Object.defineProperty(obj, prop, descriptor)來追蹤狀態變化。
  • 直接修改狀態爲指定值,而後接着執行回調

嗚嗚嗚,有時候總會犯傻不是,上面第一種維護一個定時器,效率低下;第二種把狀態變得很麻煩和複雜;
其實不少事情之因此複雜,是由於咱們想的太多。
Promise根本沒那麼複雜,就三個狀態,搞毛線定時器,狀態跟蹤。
利用觀察者模式,只須要經過特定書寫方式註冊對應狀態的事件處理函數,而後更新狀態,調用註冊過的處理函數便可。這個特定方式就是 then ,done ,fail, always...等方法;更新狀態觸發時機就是resolve, reject方法。app

簡單實現

理論分析:異步

  • 寫一個類對象,維護一個 state,值有3種:"pending", "resolved", "rejected"
  • 經過then done fail always方法註冊回調處理函數
  • 經過resolve reject分別更新對應狀態,而且調用註冊函數

代碼以下:函數

/**
 * [3種狀態]
 * @type {String}
 */
var PENDING = "pending";
var RESOLVED = "resolved";
var REJECTED = "rejected";

/**
 * [Promise類實現]
 * 構造函數傳入一個fn,有兩個參數,resolve:成功回調; reject:失敗回調;
 * state: 狀態存儲
 * doneList: 成功處理函數列表
 * failList: 失敗處理函數列表
 * done: 註冊成功處理函數
 * fail: 註冊失敗處理函數
 * then: 同時註冊成功和失敗處理函數
 * always: 一個處理註冊到成功和失敗,都會調用
 * resolve: 更新state爲:RESOLVED,而且執行成功處理隊列
 * reject: 更新state爲:REJECTED,而且執行失敗處理隊列
 */
var Promise = (function (){
    function Promise(fn){
        this.state = PENDING;
        this.doneList = [];
        this.failList = [];
        this.fn = fn;
        this.fn(this.resolve.bind(this), this.reject.bind(this))
    }

    var p = {
        done: function (cb){
            if(typeof cb == "function")
                this.doneList.push(cb)
            return this;
        },
        fail: function(cb){
            if(typeof cb == "function")
                this.failList.push(cb);
            return this;
        },
        then: function(success, fail){
            this.done(success || noop).fail(fail || noop)
            return this;
        },
        always: function(cb){
            this.done(cb).fail(cb)
            return this;
        },
        resolve: function(){
            this.state = RESOLVED;
            var lists = this.doneList;
            for(var i = 0, len = lists.length; i<len; i++){
                lists[0].apply(this, arguments);
                lists.shift();
            }
            return this;
        },
        reject: function(){
            this.state = REJECTED;
            var lists = this.failList;
            for(var i = 0, len = lists.length; i<len; i++){
                lists[0].apply(this, arguments);
                lists.shift();
            }
            return this;
        }
    }
    for(var k in p){
        Promise.prototype[k] = p[k]
    }

    return Promise;
})();

function noop(){}

使用方式,請到https://github.com/donglegend/MyPromise下載使用oop

源碼下載

相關文章
相關標籤/搜索