/**
     * Promise对象的内部状态
     *
     * @type {Object}
     */
    var Status = {
      PENDING: 'pending',
      FULLFILLED: 'resolved',
      REJECTED: 'rejected'
  };

  function empty() {}

  /**
   * Promise构造函数
   *
   * @constructor
   * @param {Function} resolver 此Promise对象管理的任务
   */
  function Promise(resolver) {
      // ES6原生的Promise构造函数中，若不通过`new`调用Promise的构造函数，会抛出TypeError异常。此处与其一致
      if (!(this instanceof Promise)) {
          throw new TypeError('TypeError: undefined is not a promise');
      }

      // ES6原生的Promise构造函数中，若无作为函数的resolver参数，会抛出TypeError异常。此处与其一致
      if (typeof resolver !== 'function') {
          throw new TypeError('TypeError: Promise resolver undefined is not a function');
      }

      /**
       * Promise对象内部的状态，初始为`pending`。状态只能由`pending`到`fullfilled`或`rejected`
       *
       * @type {string}
       */
      this._status = Status.PENDING;

      /**
       * Promise对象resolved/rejected后拥有的data/reason
       *
       *  - 此处保存此值是为了当一个Promise对象被resolved或rejected后，继续对其调用`then`添加任务，后续处理仍能获得当前Promise的值
       *
       * @type {Mixed}
       */
      this._value;

      /**
       * 当前Promise被resolved/rejected后，需处理的任务
       *
       *  - 由于同一个Promise对象可以调用多次`then`方法，以添加多个并行任务，所以此处是一个数组
       *
       * @type {Array.<Function>}
       */
      this._doneCallbacks = [];
      this._failCallbacks = [];

      var promise = this;
      resolver(
          function (data) {
              resolve(promise, data);
          },
          function (reason) {
              reject(promise, reason);
          }
      );
  }

  Promise.prototype = {

      constructor: Promise,

      /**
       * Promise的`then`方法
       *
       * @param {Function|Mixed} onResolve 当前Promise对象被resolved后，需处理的任务
       * @param {Function|Mixed} onReject 当前Promise对象被rejected后，需处理的任务
       * @return {Promise} 返回一个新的Promise对象，用于链式操作
       */
      then: function (onResolve, onReject) {
          var promise = new Promise(empty);

          this._doneCallbacks.push(makeCallback(promise, onResolve, 'resolve'));
          this._failCallbacks.push(makeCallback(promise, onReject, 'reject'));

          // 如果在一个已经被fullfilled或rejected的promise上调用then，则需要直接执行通过then注册的回调函数
          run(this);

          return promise;
      },

      /**
       * Promise的`done`方法
       *
       * @param {Function|Mixed} onResolve 当前Promise对象被resolved后，需处理的任务
       * @return {Promise} 返回一个新的Promise对象，用于链式操作
       */
      done: function (onResolve) {
          return this.then(onResolve, null);
      },

      /**
       * Promise的`fail`方法
       *
       * @param {Function|Mixed} onReject 当前Promise对象被rejected后，需处理的任务
       * @return {Promise} 返回一个新的Promise对象，用于链式操作
       */
      fail: function (onReject) {
          return this.then(null, onReject);
      },

      /**
       * Promise的`catch`方法
       *
       * @param {Function|Mixed} onFail 当前Promise对象被rejected后，需处理的任务
       * @return {Promise} 返回一个新的Promise对象，用于链式操作
       */
      catch: function (onFail) {
          return this.then(null, onFail);
      }
  };

  /**
   * 创建一个Promise对象，并用给定值resolve它
   *
   * @param {Mixed} value 用于resolve新创建的Promise对象的值
   * @return {Promise} 返回一个新的Promise对象，用于链式操作
   */
  Promise.resolve = function (value) {
      var promise = new Promise(empty);
      resolve(promise, value);
      return promise;
  };

  /**
   * 创建一个Promise对象，并用给定值reject它
   *
   * @param {Mixed} reason 用于reject新创建的Promise对象的值
   * @return {Promise} 返回一个新的Promise对象，用于链式操作
   */
  Promise.reject = function (reason) {
      var promise = new Promise(empty);
      reject(promise, reason);
      return promise;
  };

  /**
   * 返回一个promise，这个promise在iterable中的任意一个promise被解决或拒绝后，
   * 立刻以相同的解决值被解决或以相同的拒绝原因被拒绝
   *
   * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
   * @return {Promise} 返回一个新的Promise对象，用于链式操作
   */
  Promise.race = function (iterable) {
      if (!iterable || !iterable.hasOwnProperty('length')) {
          throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
      }

      var promise = new Promise(empty);
      for (var i = 0, len = iterable.length; i < len; i++) {
          var iterate = iterable[i];
          if (!(iterate instanceof Promise)) {
              iterate = Promise.resolve(iterate);
          }

          iterate.then(resolveRaceCallback, rejectRaceCallback);
      }

      var settled = false;

      function resolveRaceCallback(data) {
          if (settled) {
              return;
          }

          settled = true;
          resolve(promise, data);
      }

      function rejectRaceCallback(reason) {
          if (settled) {
              return;
          }

          settled = true;
          reject(promise, reason);
      }
  };

  /**
   * 返回一个promise，该promise会在iterable参数内的所有promise都被解决后被解决
   *
   * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
   * @return {Promise} 返回一个新的Promise对象，用于链式操作
   */
  Promise.all = function (iterable) {
      if (!iterable || !iterable.hasOwnProperty('length')) {
          throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
      }

      var promise = new Promise(empty);
      var length = iterable.length;
      for (var i = 0; i < length; i++) {
          var iterate = iterable[i];
          if (!(iterate instanceof Promise)) {
              iterate = Promise.resolve(iterate);
          }

          iterate.then(makeAllCallback(iterate, i, 'resolve'), makeAllCallback(iterate, i, 'reject'));
      }

      var result = [];
      var count = 0;

      function makeAllCallback(iterate, index, action) {
          return function (value) {
              if (action === 'reject') {
                  reject(promise, value);
                  return;
              }

              result[index] = value;

              if (++count === length) {
                  resolve(promise, result);
              }
          }
      }
  };

  /**
   * 返回一个Deferred对象，包含一个新创建的Promise对象，以及`resolve`和`reject`方法
   *
   * @return {Deferred}
   */
  Promise.defer = function () {
      var promise = new Promise(empty);

      return {
          promise: promise,
          resolve: function (data) {
              resolve(promise, data);
          },
          reject: function (reason) {
              reject(promise, reason);
          }
      };
  };

  function run(promise) {
      // `then`方法中也会调用，所以此处仍需做一次判断
      if (promise._status === Status.PENDING) {
          return;
      }

      var value = promise._value;
      var callbacks = promise._status === Status.FULLFILLED
          ? promise._doneCallbacks
          : promise._failCallbacks;

      // Promise需要异步操作
      setTimeout(function () {
          for (var i = 0, len = callbacks.length; i < len; i++) {
              callbacks[i](value);
          }
      });

      // 每个promise只能被执行一次。虽然`_doneCallbacks`和`_failCallbacks`用户不应该直接访问，
      // 但还是可以访问到，保险起见，做清空处理。
      promise._doneCallbacks = [];
      promise._failCallbacks = [];
  }

  function resolve(promise, data) {
      if (promise._status !== Status.PENDING) {
          return;
      }

      promise._status = Status.FULLFILLED;
      promise._value = data;

      run(promise);
  }

  function reject(promise, reason) {
      if (promise._status !== Status.PENDING) {
          return;
      }

      promise._status = Status.REJECTED;
      promise._value = reason;

      run(promise);
  }

  function makeCallback(promise, callback, action) {
      return function promiseCallback(value) {
          // 如果传递了callback，则使用前一个promise传递过来的值作为参数调用callback，
          // 并根据callback的调用结果来处理当前promise
          if (typeof callback === 'function') {
              var x;
              try {
                  x = callback(value);
              }
              catch (e) {
                  // 如果调用callback时抛出异常，则直接用此异常对象reject当前promise
                  reject(promise, e);
              }

              // 如果callback的返回值是当前promise，为避免造成死循环，需要抛出异常
              // 根据Promise+规范，此处应抛出TypeError异常
              if (x === promise) {
                  var reason = new TypeError('TypeError: The return value could not be same with the promise');
                  reject(promise, reason);
              }
              // 如果返回值是一个Promise对象，则当返回的Promise对象被resolve/reject后，再resolve/reject当前Promise
              else if (x instanceof Promise) {
                  x.then(
                      function (data) {
                          resolve(promise, data);
                      },
                      function (reason) {
                          reject(promise, reason);
                      }
                  );
              }
              else {
                  var then;
                  (function resolveThenable(x) {
                      // 如果返回的是一个Thenable对象（此处逻辑有点坑，参照Promise+的规范实现）
                      if (x && (typeof x === 'object'|| typeof x === 'function')) {
                          try {
                              then = x.then;
                          }
                          catch (e) {
                              reject(promise, e);
                              return;
                          }

                          if (typeof then === 'function') {
                              // 调用Thenable对象的`then`方法时，传递进去的`resolvePromise`和`rejectPromise`方法（及下面的两个匿名方法）
                              // 可能会被重复调用。但Promise+规范规定这两个方法有且只能有其中的一个被调用一次，多次调用将被忽略。
                              // 此处通过`invoked`来处理重复调用
                              var invoked = false;
                              try {
                                  then.call(
                                      x,
                                      function (y) {
                                          if (invoked) {
                                              return;
                                          }
                                          invoked = true;

                                          // 避免死循环
                                          if (y === x) {
                                              throw new TypeError('TypeError: The return value could not be same with the previous thenable object');
                                          }

                                          // y仍有可能是thenable对象，递归调用
                                          resolveThenable(y);
                                      },
                                      function (e) {
                                          if (invoked) {
                                              return;
                                          }
                                          invoked = true;

                                          reject(promise, e);
                                      }
                                  );
                              }
                              catch (e) {
                                  // 如果`resolvePromise`和`rejectPromise`方法被调用后，再抛出异常，则忽略异常
                                  // 否则用异常对象reject此Promise对象
                                  if (!invoked) {
                                      reject(promise, e);
                                  }
                              }
                          }
                          else {
                              resolve(promise, x);
                          }
                      }
                      else {
                          resolve(promise, x);
                      }
                  }(x));
              }
          }
          // 如果未传递callback，直接用前一个promise传递过来的值resolve/reject当前Promise对象
          else {
              action === 'resolve'
                  ? resolve(promise, value)
                  : reject(promise, value);
          }
      };
  }

  module.exports = Promise