promise

107 阅读3分钟
/**
 * 
 * 问题1:怎么调用第二个then的onFullfilled函数呢
 * 这也就是为啥我们要把第一个第一个promise中then的执行代码放到promise2中的原因
 * 根据使用Promise我们知道:
 *    promise2是立即执行的,不影响执行顺序
 *    第一个promise的onfullfilled函数的执行结果会传递个第二个then中,那么我们就把第一个then中
 * 
 * 
 * 
 * 问题2:resolvePromise是用来具体做什么的?
 * 其实就是用来处理第一个promise返回的值X的
 */


function Promise(executor) {
    let self = this;
    self.status = "pending";
    self.value = undefined;
    /* 
        这里为啥是个数组呢?什么时候会出现多个数组元素
        这里用了发布订阅模式:数组用来保存成功和失败的回调函数
        因为如果是异步的话,状态还未改变
    */
    self.onResolvedCallbacks = [];
    self.onRejectedCallbacks = [];
    function resolve(value) {
      if (value instanceof Promise) {
        /**
         * 为啥返回的是value.then()
         * 
        */ 
        return value.then(resolve, reject)
      }
      setTimeout(function () { 
        /**
         * 为啥异步执行所有的回调函数:
         *  */ 
        if (self.status == 'pending') {
          self.value = value;
          // 改变状态为成功
          self.status = 'resolved';
          // 让所有的成功函数执行
          self.onResolvedCallbacks.forEach(item => item(value));
        }
      });
  
    }
  
    function reject(value) {
      setTimeout(function () {
        if (self.status == 'pending') {
          self.value = value;
          // 改变状态为失败
          self.status = 'rejected';
          // 让所有的失败函数执行
          self.onRejectedCallbacks.forEach(item => item(value));
        }
      });
    }
  
    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }


  // promise2 的成功或者失败取决于X
  function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
      return reject(new TypeError('循环引用'));
    }
    let then, called;
  
    if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
      try {
        // 取then可能会发生异常,不可枚举,不可以枚举的话直接reject(e);
        // 缓存了then
        then = x.then;
        if (typeof then == 'function') {
          // 这里用缓存的then,不要每次取x对象上找then,执行效率问题
          then.call(x, function (y) {
            if (called)return;
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          }, function (r) {
            if (called)return;
            called = true;
            reject(r);
          });
        } else {
          resolve(x);
        }
      } catch (e) {
        if (called)return;
        called = true;
        reject(e);
      }
    } else {
      resolve(x);
    }
  }
  Promise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    /**
     * 这里为啥要做是不是函数的判断?
     */
    onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : function (value) {
      return value
    };
    onRejected = typeof onRejected == 'function' ? onRejected : function (value) {
      throw value
    };
    let promise2;
    if (self.status == 'resolved') {
      /**
       * 第一个promise不管成功还是失败,只要报错了就走第二个失败,只要不报错,那就走resolve,有resolve中去做具体判断
       */
      promise2 = new Promise(function (resolve, reject) {
        /**
         * 这里为啥是异步的
         * Q2:这也就是为啥我们要把第一个第一个promise中then的执行代码放到promise2中的原因
         * 
         */
        setTimeout(function () {
          /**
             * 这里为啥是异步的!!!!!!!!!!!
             * 原因就是在resolvePromise(promise2, x, resolve, reject)中使用了promise2,还没有声明promise2呢
             * 类似于这个测试用例
              function Test() {
                  setTimeout(() => {
                      console.log(a)
                  })
              }
              let a = new Test()
              // 居然报错了: a is not defined 因为先new对象再声明变量,这个变量没有声明呢,如果变成异步的就好了
          */
          try {
            /**
             * 为啥要把这段函数放在promise2里面执行呢?为啥要获取到x并且传给resolvePromise
             * 因为resolvePromise是用来判断x的,根据x来决定promise2的成功或者失败
             * 注意这里所有的都得捕获异常,并且捕获到的异常都要交给下一个then的onReject处理
             */
            let x = onFulfilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
  
      });
    }
    if (self.status == 'rejected') {
      promise2 = new Promise(function (resolve, reject) {
        setTimeout(function () {
          try {
            // 注意这里所有的都得捕获异常,并且捕获到的异常都要交给下一个then的onReject处理
            let x = onRejected(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });
    }
    if (self.status == 'pending') {
      promise2 = new Promise(function (resolve, reject) {
        self.onResolvedCallbacks.push(function (value) {
          try {
            // 注意这里所有的都得捕获异常,并且捕获到的异常都要交给下一个then的onReject处理
            let x = onFulfilled(value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
        self.onRejectedCallbacks.push(function (value) {
          try {
            // 注意这里所有的都得捕获异常,并且捕获到的异常都要交给下一个then的onReject处理
            let x = onRejected(value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });
    }
    return promise2;
  }
  Promise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected);
  }
  Promise.all = function (promises) {
    return new Promise(function (resolve, reject) {
      let result = [];
      let count = 0;
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(function (data) {
          result[i] = data;
          if (++count == promises.length) {
            resolve(result);
          }
        }, function (err) {
          reject(err);
        });
      }
    });
  }
  
  Promise.deferred = Promise.defer = function () {
    var defer = {};
    defer.promise = new Promise(function (resolve, reject) {
      defer.resolve = resolve;
      defer.reject = reject;
    })
    return defer;
  }
  try {
    module.exports = Promise
  } catch (e) {
  }