手写Promise

67 阅读2分钟

Promise 有几个 重要的点:

1、promise有三种状态,等待(pending)、已完成(fulfilled)、已拒绝(rejected)

2、promise的状态只能从“等待”转到“完成”或者“拒绝”,不能逆向转换,同时“完成”和“拒绝”也不能相互转换

3、promise必须有一个then方法,而且要返回一个promise,供then的链式调用,也就是可thenable的

4、then接受俩个回调(成功与拒绝),在相应的状态转变时触发,回调可返回promise,等待此promise被resolved后,继续触发then链

一般我们会这么使用Promise:

var promise = new Promise(function(resolve, reject) {
    setTimeout(function(){
        resolve("val")
    })
})
promise.then(onFulfilled,onRejected).then(onFulfilled,onRejected)

我们可以直接对返回的promise对象进行操作,比如then,传入回调,

这里的函数并不会立即执行,而是加入队列,等待未来的某个时间resolve时被触发执行。

实现Promise构造函数

根据Promise实现要点1,定义三个状态

var PENDING = undefined, FULFILLED = 1, REJECTED = 2;

然后实现Promise构造函数,此函数接受一个函数参数,函数参数接受俩个我们提供的方法resolve与reject,供使用者在未来的某个时间里调用触发执行我们的队列

这里还要初始下当前的状态,传递的值,以及then时保存到的队列。

var Promise = function(resolver){
    if (!isFunction(resolver))
        throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");
    if(!(this instanceof Promise)) return new Promise(resolver);

    var promise = this;
    promise._value;
    promise._reason;
    promise._status = PENDING;
    promise._resolves = [];
    promise._rejects = [];

    var resolve = function(value){
        //状态转换为FULFILLED 
        //执行then时保存到_resolves里的回调,
        //如果回调有返回值,更新当前_value
    }
    var reject = function(reason){
        //状态转换为REJECTED
        //执行then时保存到_rejects里的回调,
        //如果回调有返回值,更新当前_rejects
    }

    resolver(resolve,reject);
}

实现then

根据Promise要点3,promise必须有一个then方法,而且要返回一个promise,供then的链式调用

而且promise.then(onFulfilled,onRejected)时,我们要判断当前promise的状态,

如果是pending则把onFulfilled与onRejected添加到_resolves与_rejects数组里,

否则的话根据状态,直接触发回调,这里要注意的是,如果返回的是promise,我们要等到此promise被resolves时,触发then链的下一个promise执行。

var isThenable = function(obj){
  return obj && typeof obj["then"] == "function";
}

Promise.prototype.then = function(onFulfilled,onRejected){
    var promise = this;
    // 每次返回一个promise,保证是可thenable的
    return Promise(function(resolve,reject){
        function callback(value){
          var ret = isFunction(onFulfilled) && onFulfilled(value) || value;
          if(isThenable(ret)){
              // 根据返回的promise执行的结果,触发下一个promise相应的状态
            ret.then(function(value){
               resolve(value); 
            },function(reason){
               reject(reason);
            });
          }else{
            resolve(ret);
          }
        }
        function errback(reason){
            reason = isFunction(onRejected) && onRejected(reason) || reason;
            reject(reason);
        }
        if(promise._status === PENDING){
               promise._resolves.push(callback);
               promise._rejects.push(errback);
           }else if(promise._status === FULFILLED){ // 状态改变后的then操作,立刻执行
               callback(promise._value);
           }else if(promise._status === REJECTED){
               errback(promise._reason);
           }
    });
}