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

源码下载

相关文章
相关标签/搜索