欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自己实现一个Promise

程序员文章站 2022-07-03 09:32:38
...
var PENDING = 0,
    FULFILLED = 1,
    REJECTED = 2;
function noop() {};
Array.isArray = Array.isArray || function (a) {
    return Object.prototype.toString.call(a) === '[object Array]';
}
function needsResolver() {
  throw new TypeError('You must pass a resolver function as the first argument to the promise constructor')
}
function needsNew() {
  throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")
}

function Promise(resolver){
    this._state = PENDING;
    this._deferredState = PENDING;
    this._result = null;
    this._deferreds = null;
    if (noop !== resolver) {
        typeof resolver !== 'function' && needsResolver();
        this instanceof Promise ? initializePromise(this, resolver) :  needsNew();
    }
}
Promise.resolve = resolve;
Promise.reject  = reject;
Promise.all  = all;
Promise.race  = race;
Promise.prototype = {
    constructor : Promise,
    then : then,
    'catch' : function _catch(onRejection) {
        return this.then(null, onRejection);
    }
}
/**
 * initializePromise 初始化 Promise 并执行 回调
 * @param promise Promise对象
 * @param resolver  回调函数
 * @param resolvePromise 回调成功后执行
 * @param rejectPromise 回调失败
 */
function initializePromise (promise, resolver) {
  try {
    resolver(function resolvePromise(value){
        _resolve(promise,value)
    },function rejectPromise(err){
        _reject(promise,err)
    })
  } catch (e) {

  }
}
/**
 * [_resolve resolve处理]
 * @param promise [Promise对象]
 * @param value   [回调参数]
 */
function _resolve (promise,value){
    if (promise._state !== PENDING) {
        return ;
    }
    promise._result = value;
    promise._state = FULFILLED;
    finale(promise);
}
/**
 * [_reject resolve处理]
 * @param promise [Promise对象]
 * @param err   [回调参数]
 */
function _reject (promise,err){
    if (promise._state !== PENDING) {
        return ;
    }
    promise._result = err;
    promise._state = REJECTED;
    finale(promise);
}

function finale (self) {
    if ( self._deferredState === 1 ) {
        handle(self, self._deferreds);
        self._deferreds = null;
    } 
}

function handle (self, deferred) {
    if (self._state === PENDING) {
        if (self._deferredState === 0) {
          self._deferredState = 1;
          self._deferreds = deferred;
          return;
        }
    }
    handleResolved(self, deferred)
}
function handleResolved (self, deferred) {
    var cb = self._state === FULFILLED ? deferred.onFulfilled : deferred.onRejected;
    if (cb === null) {
      if (self._state === FULFILLED) {
        _resolve(deferred.promise, self._value);
      } else {
        _reject(deferred.promise, self._value);
      }
      return;
    }
    cb(self._result);
    if ( self._state === REJECTED ) {
      _reject(deferred.promise, self._result);
    } else {
      _resolve(deferred.promise, self._result);
    }
}

function Handler(onFulfilled, onRejected, promise){
  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  this.promise = promise;
}
/**
 * [then 异步回调]
 * @param  {[function]} resolve [resolve回调]
 * @param  {[function]} reject  [reject回调]
 */

function then (resolve,reject) {
    var res = new Promise(noop);
    handle(this, new Handler(resolve, reject, res));
    return res;
}

/**
 * @param  {[promise]}  object  返回一个promise对象
 * @param  {[string]}   object  返回一个promise对象 并且resolve返回object
 */
function resolve (object) {
    var Constructor = this;
    if( object && 
        typeof object === 'object' && 
        object.constructor === Constructor
    ) {
        return object;
    }
    var promise = new Constructor(noop);
    _resolve(promise, object)
    return promise;
}

function reject (object) {
    var Constructor = this;
    var promise = new Constructor(noop);
    _reject(promise, object)
    return promise;
}

function all (arr) {
    if ( !Array.isArray(arr) ) {
        return new Error('Array Methods must be provided an Array');
    }
    var args = Array.prototype.slice.call(arr);
    return new Promise(function (resolve, reject) {
        if (args.length === 0) return resolve([]);
        var len = args.length;
        var result = [];
        function res(i,val) {
            if ( val && (typeof val === 'object' || typeof val === 'function') ) {
                if (val instanceof Promise ) {
                    if ( val._state === REJECTED ) reject(val._result);
                    if ( val._state === FULFILLED ) res(i,value);
                    if ( val._state === PENDING ) {
                        val.then(function(value) {
                            res(i,value)
                        }, function( error) {
                            reject(error)
                        })
                    } 
                    return;
                } 
            } 
            result[i] = val;
            if (--len === 0) {
              resolve(result);
            }
        }
        for (var i = 0; i < args.length; i++) {
          res(i, args[i]);
        }
    })
}
function race (arr) {
      return new Promise(function (resolve, reject) {
        arr.forEach(function(value){
          Promise.resolve(value).then(resolve, function(error){});
        });
      });
}